home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / libs / anivga12 / anivga.doc < prev    next >
Text File  |  1993-07-11  |  226KB  |  4,589 lines

  1.        ░░░░░░▄ ░░░▄ ░░▄ ░░░░░░▄                ░░▄ ░░▄  ░░░░▄  ░░░░░░▄
  2.        ░░█▀░░█ ░░░░▄░░█   ░░█▀▀                ░░█ ░░█ ░░█▀▀▀  ░░█▀░░█
  3.        ░░░░░░█ ░░█░░░░█   ░░█      ░░░░░░▄     ░░█ ░░█ ░░█░░░▄ ░░░░░░█
  4.        ░░█▀░░█ ░░█ ░░░█   ░░█       ▀▀▀▀▀▀      ░█ ░█▀ ░░█ ░░█ ░░█▀░░█
  5.        ░░█ ░░█ ░░█  ░░█ ░░░░░░▄                  ░░█▀   ░░░░█▀ ░░█ ░░█
  6.         ▀▀  ▀▀  ▀▀   ▀▀  ▀▀▀▀▀▀                   ▀▀     ▀▀▀▀   ▀▀  ▀▀
  7.  
  8.  
  9.                          ░░░░░▄  ░░░░░░▄  ░░░░▄
  10.                          ░░█▀░░▄ ░░█▀░░█ ░░█▀░░▄
  11.                          ░░█ ░░█ ░░█ ░░█ ░░█  ▀▀
  12.                          ░░█ ░░█ ░░█ ░░█ ░░█ ░░▄
  13.                      ░░▄ ░░░░░█▀ ░░░░░░█  ░░░░█▀
  14.                       ▀▀  ▀▀▀▀▀   ▀▀▀▀▀▀   ▀▀▀▀
  15.  
  16.                         (English documentation)
  17.  
  18.             ┌─────────────────────────────────────────────┐
  19.             │                   AniVGA                    │
  20.             │     a sprite-unit for TurboPascal ≥V6.0     │
  21.             │              by Kai Rohrbacher              │
  22.             │                 Version 1.2                 │
  23.             └─────────────────────────────────────────────┘
  24.  
  25.  
  26. Purpose : Animation of sprites on a VGA's 320x200x256 mode and
  27.           TurboPascal ≥V6.0
  28. Author  : Kai Rohrbacher
  29.           Germany
  30.           Internet: S_ROHRBACHER@IRAVCL.IRA.UKA.DE
  31.           Bitnet  : UKB8@DKAUNI2.BITNET
  32.           FIDO    : 2:241/7451.7 (aka Kai.Rohrbacher@logo.ka.sub.org)
  33.                     (note: due to the German putsch in FIDO, you
  34.                      won't reach me at 2:241/7451 if writing from
  35.                      outside Germany!)
  36. Language: TurboPascal V6.0
  37. Date    : June 1993
  38.  
  39. ---------------------------------------------------------------------
  40. Always remember: "I know my English spelling is bad, but if I used my
  41.                   own language you probably couldn't read it at all."
  42.                                                      -- Nico de Vries
  43. ---------------------------------------------------------------------
  44.  
  45. 0. Table of contents
  46. ────────────────────
  47.  
  48.   1. Prélude: Legal Notices
  49.   2. What is AniVGA? How to install?
  50.   3. Features and Restrictions of AniVGA
  51.   4. "HELLO WORLD" - A First Example
  52.   5. How AniVGA works
  53.   6. Tips, tricks and techniques
  54.   7. Credits
  55.   8. AniVGA Reference Manual
  56.  
  57.  
  58. 1. Prélude: Legal Notices
  59. ─────────────────────────
  60.  
  61. Okay, the boring stuff first...
  62.  
  63. The author hereby disclaims all warranties relating to this software,
  64. whether expressed or implied, including without limitation any implied
  65. warranties of merchantability or fitness for a particular purpose.
  66. I will not be liable for any special, incidental, consequential, indirect
  67. or similar damages due to loss of data/damage to hardware or any other
  68. reason, even if I have been advised of the possibility of such damages.
  69.  
  70. This programming toolkit is released as "freeware" by the author.
  71. It is however copyrighted and all rights and ownership are kept with the
  72. author. You may use it, copy it and give it to everybody as long as no
  73. modifications are made  -- but don't try to sell it (or part of it)!
  74. You may freely copy and give away this program package as long as you...
  75. a) don't make any changes to the code    -and-
  76. b) don't omit any files from the archive
  77.  
  78. All programs you realize with this software package may be distributed/sold
  79. freely - the only thing I ask you for is to mention the use of this toolkit
  80. in your program and to send me a copy of your program, although a small
  81. donation would be *much* appreciated, for the reasons told in the file
  82. README.2ND (which I hope, you have read thoroughly!).
  83.  
  84.  
  85. 2. What is AniVGA? How to install?
  86. ──────────────────────────────────
  87.  
  88. AniVGA is a powerful toolkit for the animation of sprites on any IBM (or com-
  89. patible) with a VGA card installed.
  90. It consists of one (big) unit compilable with TurboPascal ≥V6.0 and some
  91. utilities to simplify its use:
  92.  
  93. README.1ST    - as it tells you: a text file you should read first
  94. README.2ND    - yes, *exactly* what you are thinking right now...
  95. ANIVGA.DOC    - the manual, you are reading it!
  96. ANIVGA.TUT    - a short tutorial
  97. ANIVGA.PAS    - the source code of the animation unit
  98. ANIVGA.ENG    - as above, but with English comments (automatically
  99.                 translated, so don't expect perfect English...)
  100.  
  101. FAQ.TXT       - some frequently asked questions
  102. CHANGES.TXT   - what has changed to the previous version of AniVGA
  103. WHATSNEW.*    - a small demo, showing some changes
  104.  
  105. COMPRESS.PAS  - code of a small compression unit used
  106. DATEIEN.PAS   - code of a unit for file selection menus & screen handling
  107. EINGABEN.PAS  - code of a unit to handle keyboard inputs
  108.  
  109. BFFFFFFF.PAS  - the source code of a (de-)compression program you can use on
  110.                 AniVGA's data files
  111. DUMP_SPR.PAS  - the source of a "sprite dumper" which disassembles a (binary)
  112.                 sprite file into a (recompilable) ASCII-text
  113. GRAB.EXE      - a TSR-program to grab sprites from other graphics (req. mouse)
  114. MAKES.PAS     - a spritemaker program (requires a mouse and a Super-VGA-card!)
  115. SHOWPIC.PAS   - the source code of a *very* small program to display a *.PIC
  116.                 file on the screen
  117. UNLIB.PAS     - the source code of a utility to break apart a library of
  118.                 sprites back into its individual sprite files
  119.  
  120. UNCHAIN.EXE   - a nice utility to avoid screen garbage when using TP's
  121.                 debugger in 320x200x256x4 graphics mode
  122. EXAMPL*.PAS   - a few _simple_ demo programs
  123.  
  124. \GRAPHICS\ *.COD, *.LIB, *.PAL, *.PIC
  125.               - some sprites, sprite-libraries, color palettes and pictures,
  126.                 used by the demo programs
  127. \FONT\ *.FNT  - the fonts usable by AniVGA
  128. \JUMPNRUN\*.* - a small (~12K) game done with AniVGA
  129.  
  130. SVGA256.BGI   - a BGI driver, only used for MAKES.EXE
  131. *.*           - documentation, sources, ...
  132.  
  133.  
  134. Installing AniVGA can be as simple as that (assuming "C:\ANIVGA12\ is the
  135. directory you want to install the programs):
  136. - Type "PKUNZIP -d ANIVGA12.ZIP C:\ANIVGA12\"  (note the "-d" option to make
  137.   the program expand the subdirectories, too!)
  138. - Make sure that TPC.EXE is on your path, change into the above directory and
  139.   run MAKE.BAT (which will compile the units & example programs)
  140. - That's all!
  141.  
  142. tpc compress
  143. tpc dateien
  144. tpc eingaben
  145. tpc anivga
  146. tpc bfffffff
  147. tpc unlib
  148. tpc dump_spr
  149. tpc makes
  150. tpc showpic
  151. for %%f in (examp*.pas) do tpc %%f
  152.  
  153. However, if you are a purist in nature :-) then alternatively...
  154. a) copy COMPRESS.PAS, DATEIEN.PAS, EINGABEN.PAS and ANIVGA.PAS to the
  155.    directory where you keep your TPU's and compile them (in the above order)
  156. b) copy the examples EXAMPLE?.PAS and all their data files *.COD, *.LIB,
  157.    *.PAL, *.FNT to whereever you keep your PAS-files, or even better: into a
  158.    new subdirectory; do so with the other *.PAS files of the utility programs
  159.    (BFFFFFFF.PAS, UNLIB.PAS, DUMP_SPR.PAS, MAKES.PAS AND SHOWPIC.PAS), too
  160. c) compile all those *.PAS files; copy the resulting EXEs (and GRAB.EXE) to a
  161.    directory where your PATH-environment variable points to
  162. d) copy the SVGA256.BGI to whereever you moved MAKES.EXE in step c)
  163. e) copy the remaining files into a new directory (or the one of step b) )
  164.  
  165. Note that these are just guidelines, you are free to come up with your own
  166. ideas where to place the files, as long as the usual TP restrictions are met:
  167. TP must find its TPUs, and EXEs must find their data files.
  168. Don't worry, TP is clever enough to tell you if it can't find something and
  169. what it was looking for.
  170.  
  171.  
  172. 3. Features and Restrictions of AniVGA
  173. ──────────────────────────────────────
  174.  
  175. Some of AniVGA's features are:
  176.  
  177.  - flickerfree animation by a "page-flipping" algorithm and using the
  178.    display enable signal
  179.  - sprite movement in any increments you want
  180.  - arbitrary background image for the animation
  181.  - windowed animations
  182.  - full use of the VGA's 256-color mode
  183.  - several sprite display methods available:
  184.    - sprites can be written normally (covering underlying figures)
  185.    - sprites can be declared to be transparent with regard to the background
  186.      or other sprites pixel by pixel
  187.    - sprites can change their color depending on the underlying background
  188.      image (-> shadow function)
  189.  - display methods can be different for each sprite
  190.  - pixel precise hit-detection routine built in
  191.  - correct clipping of sprites at the screen boundaries
  192.  - up to 32767 different sprites
  193.  - up to 500 sprites may be simultaneously active
  194.  - maximal size of each sprite = 64k
  195.  - maximal size of all loaded sprites only restricted by available memory
  196.  - works with virtual coordinates in the range -16000..+16000
  197.  - thus simple creation of horizontal/vertical "scrolling" games
  198.  - scrolling background image, too
  199.  - several supporting routines to: drawing lines (with built in clipping-
  200.    algorithm), points and graphic-text (incl. clipping), automatic heap
  201.    management for loading of sprites, sprite libraries, background images,
  202.    processor-speed adjustment, palette handling,...
  203.  
  204. What AniVGA does _not_ support:
  205.  - XMS memory  (to slow)
  206.  - resolutions other than 320x200x256  (compatibility question)
  207.  
  208.  
  209. 4. "HELLO WORLD" - A First Example
  210. ──────────────────────────────────
  211.  
  212. AniVGA uses a non-standard 320x200x256 graphic mode, different from the BIOS-
  213. mode $13, but there should be no problems with all truly compatible VGA cards.
  214. To see if AniVGA is compatible with your system and to get a first impression
  215. of its ease of use, compile the following _simple_ program (you can find it on
  216. disk as file "EXAMPLE1.PAS"):
  217.  
  218. Notes:
  219.  - Remember to copy and compile AniVGA.PAS in your TurboPascal-Unit-directory
  220.    first!
  221.  - If you want to single-step through the program using TP's built-in debugger,
  222.    then start TP by typing "UNCHAIN TURBO.EXE" (make sure UNCHAIN.EXE is in
  223.    the same directory as TURBO.EXE or somewhere where it will be found by Dos).
  224.    (If you still get screen garbage, then you forgot to enable one or both of
  225.     the options "Graphics screen save" and/or "EGA/VGA palette save" in menu
  226.     Options -> Environment -> Startup)
  227.  
  228. PROGRAM Example1;
  229. USES AniVGA,CRT;
  230. CONST LoadNumber=42; {why not 42? - A hello to all Douglas Adam fans!}
  231.       SpriteName='FLOWER.COD'; {Path and name of the sprite to load}
  232.       Sprite1=0;
  233.       Sprite2=5;
  234.       ch:CHAR=#0; {sets ch to that value everytime the program starts}
  235. VAR collide:BOOLEAN;
  236.  
  237. BEGIN
  238.  IF loadSprite(SpriteName,LoadNumber)=0
  239.   THEN BEGIN
  240.         CloseRoutines;
  241.         WRITELN('Error: '+GetErrorMessage); halt(1)
  242.        END;
  243.  
  244.  InitGraph;
  245.  
  246.  Color:=66;
  247.  BackgroundLine(0,0,XMAX,0); BackgroundLine(XMAX,0,XMAX,YMAX);
  248.  BackgroundLine(XMAX,YMAX,0,YMAX); BackgroundLine(0,YMAX,0,0);
  249.  BackgroundOutTextXY(100,70,'Hello world!');
  250.  
  251.  SpriteN[Sprite1]:=LoadNumber;
  252.  SpriteX[Sprite1]:=0; SpriteY[Sprite1]:=0;
  253.  
  254.  SpriteN[Sprite2]:=LoadNumber;
  255.  SpriteX[Sprite2]:=XMAX SHR 1; SpriteY[Sprite2]:=YMAX SHR 1;
  256.  
  257.  Animate;
  258.  REPEAT
  259.   collide:=Hitdetect(Sprite1,Sprite2);
  260.   if collide THEN BEGIN Sound(1000); Delay(5); NoSound END;
  261.   if KeyPressed
  262.    THEN BEGIN
  263.          WHILE KeyPressed do ch:=UpCase(ReadKey);
  264.          CASE ch OF
  265.           'I':DEC(SpriteY[0]);
  266.           'J':DEC(SpriteX[0]);
  267.           'K':INC(SpriteX[0]);
  268.           'M':INC(SpriteY[0]);
  269.           'E':dec(StartVirtualY,10);  {change position of whole scene with}
  270.           'S':dec(StartVirtualX,10);  {E,S,D,X}
  271.           'D':inc(StartVirtualX,10);
  272.           'X':inc(StartVirtualY,10);
  273.          END;
  274.          IF POS(ch,'IJKMESDX')>0 THEN Animate;
  275.         END;
  276.  
  277.  UNTIL (ch='Q') OR (ch=#27);
  278.  
  279.  CloseRoutines;
  280. END.
  281.  
  282. (Don't worry if you do not understand the whole program at once - it should
  283.  only give you a first impression of AniVGA's capabilities)
  284. If you run this program (make sure that the sprite file FLOWER.COD can be
  285. found by the program!) you should see a graphic consisting of two flowers, a
  286. rectangle showing the screen boundaries and the words "Hello world" near the
  287. middle of the screen.
  288. You can move the top left flower by using the keys "I","J","K","M".
  289. If you hit the other flower with the first one, the program will beep.
  290. Try out what happens if you move across the two words in the middle:
  291. obviously, the two leafs of the sprite behave somehow different: the black
  292. parts of left leaf are "transparent" in that the writing shines through it,
  293. while the black parts of the right leaf are "covering black".
  294. But the writing (which is written in the background image) won't be destroyed.
  295. As soon as you leave them, the words will be alright again.
  296. Move the sprite to the very left screen boundary - and move it even more to
  297. the left: you'll get the impression that it moves off the screen until it is
  298. totally offscreen.
  299. Hmmmm - how do we get it back? Sure, "K" will do, but press "S" instead: this
  300. will "pan" the whole screen 10 pixels to the left (think of that as if you
  301. could control an imaginary camera to slide to the left), "X" pans into the
  302. other direction (note the restriction of the program to non-scrolling back-
  303. ground at this point: the big rectangle and the words "Hello world" won't
  304. move because they are part of the so-called "static" background image).
  305. ("E" and "X" will behave similarily, but for the y-direction.)
  306. Now -using the "I","J","K" and "M" keys- bring back your sprite to the 2nd one
  307. and let them collide. Press "A" a few times to scroll them both offscreen.
  308. As you'll notice, the program will not stop beeping: it indicates that the two
  309. sprites collide, even if they are not visible to you!
  310. Okay, that should be enough for a first impression, so hit "Q" (or ESC) to
  311. quit the program, if you've finished wondering... :-)
  312.  
  313. There are a few more EXAMPLE programs included. They share a common thing:
  314. they are as small and simple as possible, because they serve only one purpose,
  315. namely to provide you with some basic techniques!
  316.  
  317. Run EXAMPLE2.PAS for a demonstration of "scrolling" background; the program is
  318. much the same as EXAMPLE1, but uses four different "tiles" to build the back-
  319. ground image. As before, you can use "I,J,K,M" to move your sprite along, but
  320. this time, you may scroll the whole scene (incl. the background!) with the
  321. "E,S,D,X" keys, too ("Q" quits, as before).
  322.  
  323. EXAMPLE3.PAS shows (an extremely) simple use of the "Display_SHADOW" mode to
  324. display a graphical object and demonstrates the difference to mode
  325. "Display_SHADOWEXACT": first, a sprite is used for its own shadow zone, simply
  326. by redrawing it with a little horizontal and vertical offset, using mode
  327. "Display_SHADOW".
  328. Although this is a nice trick with many sprites (you don't have to design
  329. extra shadow sprites this way), it doesn't always work: note that there is one
  330. area in the flower which differs from what we would expect as shadow: this is
  331. because AniVGA assumes that everything between the left- and rightmost point
  332. of a sprite belongs to the sprite's interior and will be drawn accordingly.
  333. To circumvent this, one would have to draw one (or even several) especially
  334. designed "shadow zone" sprites for the flower, or use Display_SHADOWEXACT
  335. instead: just press the space bar to toggle to that mode.
  336. Pressing "P" draws 1000 randomly distributed points so you can better see the
  337. shadowing effect for single points.
  338. Finally, "C" copies part of the screen into memory (with GetImage() ) and
  339. pastes it somewhere else (with PutImage() ) while clipping off at the screen
  340. boundaries and is merely there to give a short demonstration of how to use
  341. these routines.
  342.  
  343. EXAMPLE4.PAS is an example how to use "sprite cycles": there are six images in
  344. the sprite (library) file HANTEL.LIB which become "glued" together to form one
  345. sprite cycle.
  346. App. one hundred copies of this sprite are then animated on the screen with
  347. maximum animation speed and again, you can scroll the whole screen area with
  348. the keys "E","S","D","X". When you do, you will note that as more and more of
  349. the sprites gets scrolled offscreen, the remaining sprites will rotate faster.
  350. Pressing the space bar will toggle between fastest animation (no time limit)
  351. and an animation rate of 200ms per frame.
  352. You can play around with this value to find out an "optimal" time for your PC
  353. and this program:
  354.  
  355.  very small: program will show the same symptoms as mentioned above (being
  356.              faster for every sprite offscreen)
  357.      .
  358.      .
  359.      .
  360.  very big  : program will slow down even when all sprites are onscreen
  361.  
  362. Somewhere between lies a value where the animation doesn't get slowed down
  363. when all sprites are onscreen (=max. work for AniVGA), but stays at the same
  364. speed for all other cases (=less work for AniVGA).
  365.  
  366. EXAMPLE5.PAS and EXAMPLE6.PAS are two programs to demonstrate how you can
  367. build a background image by using tiles: a 2x2 (8x4 respectively) COD-file
  368. will be loaded and pasted repetively into the virtual screen.
  369. EXAMPLE6.PAS also shows how you may tie sprites and text output to an absolute
  370. screen position in scrolling background modes! Besides that, it demonstrates
  371. usage of a loadable (and multi colored) font.
  372.  
  373. EXAMPLE7.PAS shows you the same old demo image of the former examples, but
  374. this time using another palette, loaded from disk.
  375.  
  376. EXAMPLE8.PAS shows you all opening sequences available by the routine
  377. "FadeIn()". Press a key A..Z (without Q) to view a method, ESC will quit.
  378.  
  379. EXAMPLE9.PAS is a simple example to demonstrate how to use an animation
  380. window by using "SetAnimateWindow()". (Don't forget to look into WHATSNEW.PAS
  381. for a bigger example).
  382.  
  383.  
  384. 5. How AniVGA works
  385. ───────────────────
  386.  
  387. (It would be _impossible_ trying to cope every detail of AniVGA, but I'm sure
  388.  you will get the basic ideas of AniVGA very soon.)
  389.  
  390. As already mentioned, the program uses a "tweaked" VGA-graphic mode: the VGA
  391. is programmed in a way to give 4 graphic pages at a resolution of 320x200
  392. pixels in 256 colors numbered 0..3.
  393. Page 0 and 1 are used for the display, page 2 holds the "normal" background
  394. image and page 3 can contain so-called "tiles" which can be used to build a
  395. huge background image in "scrolling" background mode.
  396. (Note for V1.2: the background page has been moved to EMS memory, but this
  397. doesn't has to bother you)
  398. The basic idea of the "page flipping" scheme used is that: do everything
  399. -erasing the old graphic page, draw sprites/lines/pixels/text- on a graphic
  400. page invisible to the user while showing him a completed page on the screen.
  401. Then, if finished, "flip" the page, thus making the new, completed page
  402. visible and the old page to the invisible one. Now start creating the next
  403. image on this new invisible page - and so on.
  404. "Erasing" the old image means: overdraw it completely with the background
  405. image stored in page 2 (or 3), so one could write in pseudo code:
  406.  
  407.    ...
  408.   REPEAT
  409.    show page 0 to user;
  410.    fill (invisible) page 1 with contents of page 2;
  411.    draw new sprites and all other stuff on page 1;
  412.    show page 1 to user;
  413.    fill (invisible) page 0 with contents of page 2;
  414.    draw new sprites and all other stuff on page 0;
  415.   UNTIL DOOMSDAY
  416.    ...
  417.  
  418. You as the programmer doesn't have to think much about this mechanism, the
  419. routines keep track of the page flipping automatically: the global variable
  420. "PAGE" always holds the number of the page which is *invisible* (and thus:
  421. the page to be drawn upon). Therefore, we say that PAGE holds the "actual
  422. page" number and 1-PAGE is the page *visible* to the user.
  423. Most of the procedures and functions of the animation package adjust them-
  424. selves to the appropriate page; there are only a few situations where you
  425. have to be aware of this mechanism, mostly when drawing pixels or to create
  426. special effects.
  427.  
  428. The whole package is "table driven". That means, the interface to the user
  429. consists of some tables in which you specify your sprites to be drawn:
  430. You store into this tables which sprites to draw ("SpriteN[]") and their
  431. coordinates (in "SpriteX[]" and "SpriteY[]").
  432. After this, a call of the main routine "Animate()" gives back control to the
  433. animation routines, which update the graphic screen accordingly:
  434.  
  435. ...
  436. REPEAT
  437.  update SpriteN[]-table:
  438.    deactivate sprite i by storing a "0" into SpriteN[i]   or
  439.    activate a sprite k by storing k in an unused SpriteN[]-entry   or
  440.    let all the other SpriteN[]-entries as they were last cycle
  441.  FOR ALL SpriteN[i]<>0 DO
  442.    IF SpriteN[i] should change its coordinates
  443.      THEN update (SpriteX[i],SpriteY[i]) accordingly
  444.  call Animate() to draw image and display it
  445. UNTIL you-become-really-bored
  446. ...
  447.  
  448. Please note that there are two kinds of "sprite numbers" which should not be
  449. mixed up: one is a spriteLOAD number and represents a handle to the (physical)
  450. sprite data, while the other (normally termed "sprite number") is a logical
  451. number to address this sprite data.
  452. In the pseudo code given above, "k" is the spriteLOAD number (it is a number
  453. given at load time) and the index "i" in SpriteN[i] is the sprite number.
  454. Note that "k" is a unique value: you can think of it as a NAME of the sprite
  455. data loaded (e.g. you could name the FLOWER.COD data as "123" when loading
  456. it: there can't be another sprite with the same LOAD-number). On the other
  457. hand, there could be a hundred flowers on the screen: just choose hundred
  458. different sprite-table entries (=sprite numbers), e.g. SpriteN[100]..
  459. SpriteN[199] and store "123" in each of them!
  460. Whenever you are unsure if you (or I) are speaking of a "sprite number" or a
  461. "spriteLOAD number", remember that:
  462.  
  463.  ■ A sprite number can hold values in the range 0..NMAX and is an index of
  464.    the tables SpriteX[], SpriteY[] and SpriteN[].
  465.  ■ A spriteLOAD number can hold values between 0..LoadMax and is assigned
  466.    as a "name" to the sprites' physical loaded data; a "0" as load number is
  467.    reserved for "inactivate sprite" (in other words, it is the *content* of
  468.    an entry in SpriteN[])
  469.  
  470. Example: SpriteN[42]:=0
  471.                  │    └ spriteLOAD number
  472.                  └ sprite number
  473.  
  474. The world AniVGA knows is 32000 pixels wide and high, numbered -16000..+16000
  475. on each axis. Because your graphic screen consists of only 320 by 200 points,
  476. (ranging from 0..XMAX and 0..YMAX in the x- and y-axis, respectively; (0,0)
  477. is the upper left corner, (XMAX,YMAX) the lower right one) you can only see
  478. a small part of this coordinate space, but AniVGA does not distinguish between
  479. the visible and invisible parts of its world. If, for example, two sprites
  480. collide, the routine "HitDetect()" will find out, even if this collision
  481. occurs offscreen.
  482. Thus you can think of your graphic display being a "camera" to the graphic
  483. space: your actions can take place everythere in this virtual world, but you
  484. see only the part displayed by your camera; if you wish to see another part
  485. of it, you have to move this imaginary camera to that place.
  486. In AniVGA, you can do this by changing the values "StartVirtualX" and
  487. "StartVirtualY" which hold the upper left corner of the visual window. As an
  488. example, let (StartVirtualX,StartVirtualY) be (1000,500): then on your screen
  489. you will see the part of the world which ranges from coordinates (1000..1319)
  490. and (500..699) in X- and Y-directions, respectively:
  491.  
  492. (-16000,-16000)
  493.  - - - - - - - - - - - - - - - - - - - - - - - -
  494. |                                               | -AniVGA's coordinate space,
  495.         █─────────────────┐-Your terminal          32000x32000 pixels in size
  496. |       │(0,0).           │ screen, 320x200     |
  497.         │      .          │ pixels in size
  498. |       │       .(319,199)│                     |  
  499.         └─────────────────┘
  500. |                                               |
  501.  
  502. |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
  503.                                           (16000,16000)
  504.  
  505.  █ = (StartVirtualX,StartVirtualY)
  506.  
  507.  
  508. 6. Tips, tricks and techniques
  509. ──────────────────────────────
  510.  
  511. There would be a lot of things to say and most of them will be mentioned in
  512. the following "Reference Manual". Nevertheless, it seems reasonable to repeat
  513. them in a more concentrated form here, although this happens to make this
  514. chapter a real topsyturvydom...
  515.  
  516. a) The ERROR-concept: if an error occurs in one of AniVGA's routines, the
  517.    global variable ERROR will be set accordingly. This gives you the freedom
  518.    either to check this variable each time you called a routine - or ignore
  519.    it for improved speed.
  520.    As a rule of thumb, you should always check this variable while your pro-
  521.    gram is still in the testing phase - and "comment out" these sections when
  522.    you are through with debugging. (Conditional defines are great for that!)
  523.  
  524.    Note that there are some routines that do not set ERROR at all (like
  525.    Screen, GetPixel, PageGetPixel, PagePutPixel), either because in some
  526.    special cases, "nice" tricks can be played with "faulty" parameters or
  527.    because of severe speed improvements! For example, if you are going to
  528.    read a 5000 pixel area from the screen with PageGetPixel(), it would be
  529.    crazy to check 5000 times whether the "page" given to read from is valid
  530.    or not.
  531.  
  532.    Errors which occur by (de)compressing compressed data are "mapped" into
  533.    normal errors of AniVGA, most often "Err_FileIO". AniVGA automatically
  534.    takes care to reset CompressError (the error variable of the compression
  535.    unit) to prevent wrong error messages.
  536.  
  537. b) Pixel-drawing routines: basically spoken, there are three sorts of graphic
  538.    data objects in AniVGA: sprites, pixels and background images.
  539.    Because of AniVGA's working scheme, all routines handling pixels
  540.    (PutPixel, PagePutPixel, Line, PutImage,...) must be used in a special
  541.    form:
  542.    - If you use them to "draw" into the background page, this can only be
  543.      done when using background mode STATIC (because in mode SCROLLING, the
  544.      background is stored in a compressed "tiling" format one can't access
  545.      directly).
  546.    - Drawing into the background page in mode STATIC is fine (that's the main
  547.      advantage of this mode compared with mode SCROLLING), and the best time
  548.      to do it is _before_ calling Animate(), because changes to the
  549.      background image will then be visible with the call to this routine.
  550.    - Drawing "on the monitor screen" will be visible exactly for one
  551.      animation cycle, that is: until the next call to Animate(). For this
  552.      reason, you must do this changes _after_ calling Animate() and at the
  553.      _visible_ page 1-PAGE (not the _actual_ page PAGE itself).
  554.  
  555.      It is not that difficult as it may sound at first glance; for example:
  556.      ...
  557.      REPEAT
  558.       read_user_inputs; compute_necessary_actions;
  559.        do_all_changes_to_the_background_image;
  560.        do_all_changes_to_the_sprites;
  561.        Animate();
  562.        do_all_changes_to_the_visible_screen;{e.g.:Line(0,0,XMAX,YMAX,1-PAGE)}
  563.      UNTIL user_wants_to_end_application
  564.      ...
  565.  
  566.      This way, after having called Animate(), the changes to the background
  567.      (and your sprites) will be visible (because Animate() has generated an
  568.      appropriate picture) and your changes to this image with the pixel-
  569.      drawing routines will be visible "at once".
  570.      That image will then stay visible until the next call to Animate().
  571.      (Simply spoken, you let Animate() generate and display a picture and then
  572.       do some changes to the picture while it is diplayed)
  573.    - Because of unavoidable memory restrictions, AniVGA can't store pixels
  574.      drawn offscreen: if AniVGA sees that points/lines lie outside the visible
  575.      screen, it just does nothing at all; in other words, you can't draw a
  576.      line outside the screen and "scroll it in" five minutes later! (You would
  577.      have to define the line as a sprite instead, because sprites are the only
  578.      objects stored independently).
  579.  
  580. c) Coordinates: Throughout all routines, AniVGA works with _virtual_
  581.    coordinates (that is values in the range xε[-16000..+16000],
  582.    yε[-16000..+16000]), but sometimes you will have to address _absolute_
  583.    coordinates (in the range xε[0..XMAX], yε[0..YMAX]), so you have to
  584.    transform virtual coordinates into absolute coordinates (or vice versa),
  585.    which is _very_ easy:
  586.  
  587.    virtual coordinates -> absolute coordinates:
  588.       Xabsolute := Xvirtual - StartVirtualX
  589.       Yabsolute := Yvirtual - StartVirtualY
  590.  
  591.    absolute coordinates -> virtual coordinates:
  592.       Xvirtual  := Xabsolute + StartVirtualX
  593.       Yvirtual  := Yabsolute + StartVirtualY
  594.  
  595. d) Background / valid pages: Many routines expect a graphic page number as
  596.    parameter. As mentioned under b), BACKGNDPAGE is valid only when you use
  597.    background mode STATIC. Nevertheless, you could draw to this page even
  598.    when you are using background mode SCROLLING without getting an error
  599.    "Err_InvalidPageNumber" (although you are _strongly_ discouraged to do
  600.    so)!
  601.    That's because you can play some tricks on AniVGA this way, provided that
  602.    you do know _exactly_ what you (and AniVGA) are doing, but this "feature"
  603.    will probably be cut off in future versions of this program.
  604.    (Note that this doesn't mean that you can't switch between STATIC and
  605.     SCROLLING backgrounds during runtime! - It only says that you can't use
  606.     the two background pages _in parallel_ (=at the same time)!)
  607.  
  608. e) Display objects at the same abolute screen position:
  609.    Let us assume you want to display a score at the upper right corner of the
  610.    screen; that's not hard when using STATIC background: just define your
  611.    score as a sprite and choose an appropriate coordinate pair.
  612.    In SCROLLING mode, your score would scroll away, too, so you must tie it
  613.    to absolute screen coordinates, as said in c), but there is a simple rule
  614.    which can be derived from the equation
  615.  
  616.       absolute_coordinate := virtual_coordinate - StartVirtual_value
  617.  
  618.    To ensure that the absolute (=screen) coordinate stays the same, you have
  619.    to balance out changes done to the StartVirtual-variables like this: when-
  620.    ever you increase/decrease StartVirtualX|Y by some amount delta, increase/
  621.    decrease your score-coordinates by the same amount delta!
  622.    (This results in: new_coord := virtual_coord±delta - (StartVirtual±delta)
  623.     = virtual_coord - StartVirtual = old_coord    as wanted)
  624.  
  625. f) Displaying scores: another way to display a score without defining it as a
  626.    sprite would be to simply draw it to the screen with the pixeldrawing rou-
  627.    tines or OutTextXY():
  628.     ■ draw it to the visible page (1-PAGE) each time after having called
  629.       ANIMATE()
  630.     ■ draw it to the background page BACKGNDPAGE
  631.    The last method is applicable only in background mode STATIC and you have
  632.    to restore the background image in the used area manually, but has the
  633.    advantage that you must redraw your score only when it really changed
  634.    (instead of every animation cycle as with the first method). One way to
  635.    accomplish that would be to use the GetImage() and PutImage() routines:
  636.    ...
  637.    build background image;
  638.    use GetImage() to get a copy of the background area which will be
  639.    overdrawn by the score;
  640.    ...
  641.    main_loop:
  642.     IF new score has to be displayed
  643.       THEN BEGIN
  644.             use PutImage() to restore old background area underneath the
  645.              score
  646.             use OutTextXY() to write new score into the background image
  647.            END
  648.    ...
  649.    ___
  650.  
  651.    Another method to accomplish drawing a score (or something similiar)
  652.    is this: use SetAnimateWindow() to restrict animations to a window smaller
  653.    than your physical terminal size of 320x200 points and draw your score to
  654.    the outer, non-animation area:
  655.    ...
  656.     SetAnimateWindow()
  657.     IF new score has to be displayed
  658.       THEN BEGIN
  659.             UpdateOuterArea:=2   {tell AniVGA to update outer area}
  660.             DoNewScore:=2        {remember this for yourself!}
  661.            END
  662.     ...
  663.      Animate;  
  664.      IF DoNewScore<>0
  665.       THEN BEGIN
  666.             draw new score to actual page
  667.             DEC(DoNewScore)
  668.            END
  669.    ...
  670.  
  671.    (Only for the interested reader:
  672.     UpdateOuterArea is a predefined variable in AniVGA, DoNewScore is a
  673.     variable you'll have to define yourself: it's necessary as you normally
  674.     will write your (outer area) graphics to *both* display pages 0 and 1
  675.     and this has to be interleaved properly with AniVGA's actions to wipe
  676.     of the old outer area contents)
  677.  
  678. g) Speed: It is hard to predict the speed of animations, because that is
  679.    merely determined by the speed of your VGA card, not your computer's CPU
  680.    clock rate! E.g., a program runs faster on my old AT (8MHz) than on a fast
  681.    (25 MHz) 80386 machine - only because of a better VGA card installed in
  682.    the AT!
  683.    Stated otherwise, if you use a computer with "enough" CPU-power, you won't
  684.    have to think much about "should I use STATIC background instead of SCROL-
  685.    LING for improved speed?", because it won't matter much anyway!
  686.    The break even point, where the VGA-card's bottle neck becomes the
  687.    limiting factor depends largely on your application (and your VGA-card, of
  688.    course), but as a rule of thumb, clock speeds faster than 12MHz won't
  689.    improve your program speeds *linearly* any further:
  690.  
  691.         animation  ^            ______
  692.         speed      │     ___----
  693.                    │    /
  694.                    │  /
  695.                    │/
  696.                    ┼─────┬───────────>  clock rate
  697.                          break-
  698.                          even point
  699.  
  700.    Note that your programs will still profit from faster CPU's, but that is
  701.    due to faster computation of all routines not limited by accessing the
  702.    video RAM; even on the fastest clones, the IBM-bus-clock-rate is not
  703.    faster than 10MHz  -- and this limits accessing the VGA card: sad, but
  704.    true...
  705.  
  706. h) DMA access: Quite a long time, I tried to speed up animation rates by
  707.    using the DMA-chip in parallel to the CPU: while the CPU is running your
  708.    program, the DMA should move around memory.
  709.    Unfortunately, I had to find out that most computers don't like DMA
  710.    memory-to-memory transfers at all and those who do don't work when
  711.    addresses used reference the video RAM area. One of you (TNX Mike!) meant
  712.    that's due to the fact that most VGA cards do not decode the necessary
  713.    DMA signals.
  714.    [comment: @!%&#*!@$ ]
  715.  
  716. i) Speedup things: Naturally, STATIC background is faster than SCROLLING
  717.    backgrounds, but you can speed up SCROLLING backgrounds, too: make sure
  718.    that StartVirtualX always is a multiple of 4 (that is, StartVirtualX
  719.    MOD 4 = 0), because then, AniVGA can (and will) use the VGA's write
  720.    mode 1 which is a lot faster than normal write mode 0.
  721.    Another idea is to shrink NMAX: if you don't need more than 100 sprites
  722.    (say), then change that constant and recompile AniVGA!
  723.  
  724.    Of course, using SetAnimateWindow() to shrink the animation window
  725.    is another possibility to speed up things.
  726.  
  727. j) GRAB: If GRAB won't pop up, then save the picture to disk (it's wise to
  728.    do that anyway), run a graphic viewer to merely display the picture and
  729.    capture then.
  730.  
  731. k) Screen garbage when using the debugger: AniVGA uses a graphics mode unknown
  732.    to TP. Therefore, single stepping or tracing will result in screen garbage.
  733.    To avoid this, just prefix calling TURBO.EXE by  UNCHAIN. For example, if
  734.    you normally would type "TURBO.EXE myprog.pas" to start TP's IDE, then now
  735.    type in "UNCHAIN TURBO.EXE myprog.pas". Happy debugging!
  736.  
  737.  
  738. 7. Credits
  739. ──────────
  740.  
  741. Honour to whom honour is due! I would like to thank some people on this way:
  742.  
  743. - Jordan Hargrave & John Bridges for the SVGA256.BGI driver (out of the
  744.   SuperVGA-driver package SVGABG40.ZIP) used in the sprite maker
  745. - Colin Buckley for his neat UNCHAIN.EXE utility
  746. - Ken Pottebaum for his TSR-unit TSRUNIT.ZIP, providing the routines necessary
  747.   to write the Grabsprite-Utility
  748. - Esra Korte & Robin Leeuwerke for their GAME.PAS demo
  749. - Joy Mukherjee for supplying the fonts of this package
  750. - Bernd Klawonn (?) for his principle of using table-driven graphics in the
  751.   first graphics toolkit I ever saw - long, long ago in the "good'ol-AppleII-
  752.   days" (~1985)
  753. - everybody else I possibly forgot
  754.  
  755.  
  756. 8. AniVGA Reference Manual
  757. ──────────────────────────
  758.  
  759. This reference manual lists all routines, variables, constants and a lot of
  760. informational stuff concerning AniVGA in alphabetic order.
  761. Don't get frightened about the amount of informations given; in normal appli-
  762. cations you will need only a few of them!
  763. (Start with looking at the example *.PAS files and play around with them
  764.  - you'll learn a whole lot more by first using them as templates than by
  765.  reading manuals!)
  766.  
  767.  
  768. ABSOLUTE COORDINATES - information
  769. ──────────────────────────────────
  770.  
  771. See       : coordinates
  772.  
  773.  
  774. ActualColors - variable
  775. ───────────────────────
  776.  
  777. Function   : Supplies the actually used palette
  778.  
  779. Declaration: VAR ActualColors:Palette;
  780.  
  781. Description: This variable holds the values of the actual graphic colors.
  782.              You can use it to change the palette, but must issue a call to
  783.              SetPalette() to make your changes visible.
  784.              E.g., to make color 5 to "mere green", you would code:
  785.               ActualColors[5].red  :=0;
  786.               ActualColors[5].green:=63;
  787.               ActualColors[5].blue :=0;
  788.               SetPalette(ActualColors,TRUE);  {or ...,FALSE}
  789.  
  790. Note       : -Whenever you change palette values by using the routine
  791.               SetPalette(), AniVGA reflects the changes in ActualColors, that
  792.               is, as long as you don't work around AniVGA's SetPalette()-
  793.               routine by directly tempering with the VGA's palette registers,
  794.               ActualColors always holds the actual palette (so you won't need
  795.               GetPalette() )
  796.  
  797. See also   : Palette, SetPalette, GetPalette
  798.  
  799.  
  800. Animate - procedure
  801. ───────────────────
  802.  
  803. Function   : Performs a complete animation cycle
  804.  
  805. Declaration: PROCEDURE Animate FAR;
  806.  
  807. Description: A call to Animate() clears the invisible graphic page by copying
  808.              the contents of the background image into the actual drawing
  809.              page (specified by variable PAGE).
  810.              Then all active sprites (SpriteN[i]<>0) in the visible window
  811.              (determined by StartVirtualX and StartVirtualY) are drawn in the
  812.              style and at the coordinates given by the user.
  813.              After that, the routine waits for the display enable signal to
  814.              reprogram the VGA adapter to flip the display pages, making the
  815.              completed image visible and changes PAGE to point to the new,
  816.              invisible graphic page.
  817.              Finally, the procedure looks how much time passed since the last
  818.              animation cycle and if this time is less than that set by
  819.              SetCycleTime(), the program waits accordingly.
  820.  
  821. Note       : This procedure is the kernel routine which has to be called
  822.              everytime when you have set all data for a new animation frame.
  823.  
  824. See also   : PAGE, SetCycleTime, StartVirtualX, StartVirtualY
  825.  
  826.  
  827. AniVGAVersion - constant
  828. ────────────────────────
  829.  
  830. Function   : Holds version number of AniVGA-unit
  831.  
  832. Declaration: CONST AniVGAVersion=11;
  833.  
  834. Description: Starting with V1.1, all versions of AniVGA will define this
  835.              constant, holding the version number of the unit.
  836.  
  837. Note       : This constant is new with version 1.1; if for some case you need
  838.              a homogenous scheme for version 1.0, too, then you must add the
  839.              definition "AniVGAVersion=10" to somewhere in the constant decla-
  840.              ration part in the interface section of AniVGA V1.0 and recompile
  841.              that unit!
  842.  
  843. See also   : -
  844.  
  845.  
  846. BackGndPage - constant
  847. ──────────────────────
  848.  
  849. Function   : Holds the page number of the backround page
  850.  
  851. Declaration: CONST BACKGNDPAGE=2;
  852.  
  853. Description: When using background mode STATIC, BackGndPage specifies the page
  854.              number of the background image for the animations to be used.
  855.  
  856. Note (!)   : Use of this constant only makes sense when using background mode
  857.              STATIC!
  858.  
  859. See also   : ScrollPage, Background
  860.  
  861.  
  862. Background - information
  863. ────────────────────────
  864.  
  865. The term "background" specifies a graphic image in front of which all anima-
  866. tions take place.
  867. There are two sorts of background in AniVGA: SCROLLING background and STATIC
  868. background, which you choose with SetBackgroundMode().
  869.  
  870. As its name states, a STATIC background cannot be scrolled: it consists of a
  871. 320x200 pixels picture.
  872. This background picture is stored in the graphic page numbered BACKGNDPAGE.
  873. At the very start of every animation cycle, the routine Animate copies that
  874. picture into the actual drawing page, thus erasing old stuff on that page and
  875. building the basis for the new image.
  876. As a normal bitmap picture, it is 320x200=64000 bytes in size. If you use the
  877. GRAB-Utility or the WritePage()-Routine to save an image, a three byte header
  878. is put ahead of the information, thus extending the size to 64003 bytes.
  879.  
  880. The second background sort is called SCROLLING: like AniVGA's virtual coor-
  881. dinates, you can define a huge background image and scroll over it.
  882. Unfortunately, it is impossible to hold a complete background picture in
  883. memory: you would need 32000*32000=1024000000 bytes RAM (!) to do that.
  884. Instead, AniVGA uses a "tiling" mechanism: tiles are small pictures (16x16
  885. pixels) which can be combined freely to build the background image.
  886. You can use up to 256 different tiles and "pin" them on an background area of
  887. up to MaxTiles (=10000) tiles; everything outside of this background area
  888. will be assigned to tile no. 0 automatically.
  889. For example, let us assume that you use only scrolling in the y-coordinate
  890. axis, 16 screens in total: thus, your x-coordinates reach from 0 to 319 and
  891. your y-coordinates from 0..(16*200-1)=5119, which gives an area of 320*5120
  892. =1638400 pixels.
  893. This is equivalent to (320/16)*(5120/16)=20*320=6400 tiles (remember: each
  894. tile consists of 16x16 pixels!).
  895. So you would define the scroll range for the background area needed with
  896. SetBackgroundScrollRange(0,0,319,5119) and start "painting" your background:
  897. You could design up to 256 different tiles and use them to assemble your
  898. background image (=those 6400 tiles).
  899. Most often, only a few are needed, because the background image isn't that
  900. dramatically different all over the place. For simplicity, let's assume that
  901. you need only 16 different tiles, numbered 0..15 respectively in the
  902. following order to build your background image:
  903.  
  904.   (0,0)                                                         (319,0)
  905.     ┌────────┬────────┬────────┐         ┌────────┬────────┬────────┐
  906.     │        │        │        │         │        │        │        │
  907.     │   0    │   1    │   2    │   ...   │   13   │   14   │   15   │
  908.     │        │        │        │         │        │        │        │
  909.     ├────────┼────────┼────────┤         ├────────┼────────┼────────┤
  910.         .        .        .                  .        .        .
  911.         .        .        .                  .        .        .
  912.         .        .        .                  .        .        .
  913.     ├────────┼────────┼────────┤         ├────────┼────────┼────────┤
  914.     │        │        │        │         │        │        │        │
  915.     │   0    │   1    │   2    │   ...   │   13   │   14   │   15   │
  916.     │        │        │        │         │        │        │        │
  917.     └────────┴────────┴────────┘         └────────┴────────┴────────┘
  918.   (0,5119)                                                      (319,5119)
  919.  
  920. Now all you have to do is to tell AniVGA that layout with the PutTile
  921. command! You _could_ do so manually:
  922.  
  923.  {assuming SetBackgroundScrollRange(0,0,319,5119) has been set}
  924.  number:=0;
  925.  y:=0; {better: y:=BackY1}
  926.  REPEAT  (things would become easier if Pascal would know a STEP-command...)
  927.   x:=0; {better: x:=BackX1}
  928.   REPEAT
  929.    PutTile(x,y,number);
  930.    number:=(number+1) MOD 16;
  931.    inc(x,16);
  932.   UNTIL x>319; {better: x>BackX2}
  933.   inc(y,16);
  934.  UNTIL y>5119; {better: y>BackY2}
  935.  
  936. That's it! (It is better to use the (global defined) "Back..."-variables,
  937. set by the former SetBackgroundScrollRange()-call, because AniVGA has to
  938. adjust values on multiples of 16, see SetBackgroundScrollRange()/Back?? for
  939. more details). But that's still to complicated: there's a routine called
  940. MakeTileArea() which does the above job more accurately:
  941. MakeTileArea(0,16,1) would do the same thing, telling AniVGA to repeat a
  942. pattern 16 tiles wide, 1 tile high and starting at tile 1 throughout the
  943. background area.
  944.  
  945. So then, why should one use STATIC backgrounds after all when there is such
  946. a powerful instrument like SCROLLING backgrounds?
  947. There are two simple answers: speed and simplicity! - First, SCROLLING back-
  948. grounds take a lot of work to compute, which slows down animations (unless
  949. you have a fast machine, because then the VGA's memory access time becomes
  950. the limiting factor). Second, it is easy to do some "tricks" on static
  951. backgrounds:
  952. draw a line in the static background page and >zap!< starting with the next
  953. animation cycle, it will be visible for all times. Stated otherwise, when
  954. using scrolling background, you cannot use drawings to the background image,
  955. because it simply doesn't exist explicitly, you are restricted solely to
  956. "tiles" and "sprites"! (On the other hand, you can play nice tricks on
  957. scrolling background by changing single tiles...)
  958. So consider carefully what mode you are going to use for your application!
  959. ___
  960. Starting with V1.2, things became even more complicated... :-)
  961. Now, AniVGA knows something called "windowed animations". This simply means
  962. that in _both_ background modes STATIC and SCROLLING, you are no more
  963. restricted to use the complete monitor area for animations: there is a new
  964. routine SetAnimateWindow() with which you can define which part of the screen
  965. area (0,0)..(XMAX,YMAX) should serve as "stage" for your animations.
  966. If you use this routine to define a window area ranging from (WinXMIN,WinYMIN)
  967. to (WinXMAX,WinYMAX), your screen layout becomes this:
  968.  
  969.  _ _ _ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
  970. |1                                               |
  971.  
  972. |                                                |
  973.             ╔═══════════════════════╗
  974. |           ║2                      ║            |
  975.             ║     ┌──────────┐      ║
  976. |           ║     │3         │      ║            |
  977.             ║     │          │      ║
  978. |           ║     └──────────┘      ║            |
  979.             ║                       ║
  980. |           ╚═══════════════════════╝            |
  981.    .                                         .
  982.    .                                         .
  983. |_ _ _ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
  984.  
  985. Area 1 is AniVGA's coordinate space, ranging form -16000 to +16000 on each
  986. axis; area 2 represents your monitor screen: its upper left corner correlates
  987. to pixel (StartVirtualX,StartVirtualY) of area 1. However, only your
  988. animation window (=area 3) works as a peephole to area 1, while area
  989. "2 minus 3" is filled with the contents of the background page.
  990. By default, area 2 = area 3, but if you want, you can shrink area 3 to
  991. whatever you want (nearly..) and set up some fancy graphics in area 2.
  992. Your animations won't "bleed out" into area 2: neither your sprites nor your
  993. background tiles or whatever!
  994. (BTW: yes, this works with background mode SCROLLING, too. That means, that
  995.  with SCROLLING backgrounds, *both* background pages (BACKGNDPAGE _and_
  996.  SCROLLPAGE) will be used: the former for area 2, the latter for for area3.
  997.  Note however that AniVGA won't care for the non-window area 2! If you draw
  998.  something to this area (for example, by using BackgroundOutTextXY() or the
  999.  other pixel drwaing routines), you MUST trigger a mechanism to make these
  1000.  changes visible, for example by the sequence "UpdateOuterArea:=2; Animate"!)
  1001.  
  1002. See also   : BACKGNDPAGE, BACKGNDADR, WritePage, LoadPage,
  1003.              WriteBackgroundPage, LoadBackgroundPage, SetBackgroundMode,
  1004.              LoadTile, Tile, SetAnimateWindow
  1005.  
  1006.  
  1007. BackgroundGetPixel - function
  1008. ─────────────────────────────
  1009.  
  1010. Function   : Reads a background pixel's color
  1011.  
  1012. Declaration: FUNCTION BackgroundGetPixel(x,y:INTEGER):BYTE; FAR;
  1013.  
  1014. Description: This routine will return the color value of the specified point
  1015.              with virtual coordinates (x,y) in the background image.
  1016.              If the corresponding absolute coordinates lie outside the screen,
  1017.              zero (= black) will be returned.
  1018.  
  1019. Note (!)   : - Use of this routine works only when using background mode
  1020.                STATIC! It might look strange to use virtual coordinates then,
  1021.                although the background is said to be static (= non-scrollable)
  1022.                and hence restricted to absolute coordinates anyway, but it is
  1023.                often convenient to use an uniform notation and it is easy to
  1024.                convert coordinates accordingly (see "coordinates" for more
  1025.                about that).
  1026.              - If you are using EMS, ensure the presence of the right EMS-
  1027.                memory block by a
  1028.                "IF EMSused THEN EnsureEMSConsistency(BackgroundEMSHandle)"
  1029.                statement!
  1030.  
  1031. See also   : coordinates, GetPixel, PageGetPixel, EMS
  1032.  
  1033.  
  1034. BackgroundLine - procedure
  1035. ──────────────────────────
  1036.  
  1037. Function   : Draws a line on the background page
  1038.  
  1039. Declaration: PROCEDURE BackgroundLine(x1,y1,x2,y2:INTEGER); FAR;
  1040.  
  1041. Description: To draw a line on the background page (thus alterating the back-
  1042.              ground), you can use this procedure. Like the similiar Line()-
  1043.              routine, it uses virtual coordinates, too.
  1044.              If necessary, the line will be clipped down to its visible part
  1045.              (using a special Sutherland-Cohen algorithm).
  1046.  
  1047. Note       : - Use of this routine only makes sense when using background
  1048.                mode STATIC!
  1049.              - An exception from this rule: if you use an animation window
  1050.                _and_ SCROLLING mode, then the non-animation-window-area is
  1051.                covered with the background image from page BACKGNDPAGE, so
  1052.                you may use this routine (and all similiar pixel drawing
  1053.                routines like BackgroundPixel() etc.).
  1054.                If you use the routine for drawing to this area, you MUST
  1055.                use "UpdateOuterArea:=2; Animate;" or a similiar mechanism
  1056.                to make these outer area changes visible!
  1057.  
  1058. See also   : Line, coordinates
  1059.  
  1060.  
  1061. BackGroundMode - variable
  1062. ─────────────────────────
  1063.  
  1064. Function   : Holds the actual choosen background mode
  1065.  
  1066. Declaration: VAR BackgroundMode:BYTE;
  1067.  
  1068. Description: Using SetBackgroundMode(), you can select one of the possible
  1069.              background modes STATIC or SCROLLING. BackGroundMode stores this
  1070.              value.
  1071.  
  1072. Note (!)   : Only read this value, never change it directly!
  1073.  
  1074. See also   : Background, SetBackgroundMode
  1075.     
  1076.  
  1077. BackgroundOutTextXY - procedure
  1078. ───────────────────────────────
  1079.  
  1080. Function   : Writes a textstring to the background page BACKGNDPAGE
  1081.  
  1082. Declaration: PROCEDURE BackgroundOutTextXY(x,y:INTEGER; s:STRING); FAR;
  1083.  
  1084. Description: This routine is exactly the same like OutTextXY() (see there), but
  1085.              it writes the string into the background page (so it will be visi-
  1086.              ble permanently).
  1087.  
  1088. Note(!)    : - Use of the routine only makes sense if STATIC is used as
  1089.                background mode. With SCROLLING backgrounds, use OutTextXY()
  1090.                instead.
  1091.              - An exception from this rule: if you use an animation window
  1092.                _and_ SCROLLING mode, then the non-animation-window-area is
  1093.                covered with the background image from page BACKGNDPAGE, so
  1094.                you may use this routine (and all similiar pixel drawing
  1095.                routines like BackgroundPixel() etc.).
  1096.                If you use the routine for drawing to this area, you MUST
  1097.                use "UpdateOuterArea:=2; Animate;" or a similiar mechanism
  1098.                to make these outer area changes visible!
  1099.  
  1100. See also   : GraphtextColor, GraphtextOrientation, GraphtextBackground,
  1101.              OutTextXY, background
  1102.  
  1103.  
  1104. BackgroundPutPixel - procedure
  1105. ──────────────────────────────
  1106.  
  1107. Function   : Plots a point into the background page
  1108.  
  1109. Declaration: PROCEDURE BackgroundPutPixel(x,y:INTEGER; color:BYTE); FAR;
  1110.  
  1111. Description: (x,y) specify the virtual coordinates of the point to be drawn in
  1112.              color "color". If this point lies onscreen (i.e.: its _absolute_
  1113.              coordinates are between (0,0)..(319,199)), it will be drawn on the
  1114.              background page BACKGNDPAGE (and become visible starting with the
  1115.              next animation cycle).
  1116.  
  1117. Note (!)   : - Use of this routine makes sense only when using background mode
  1118.                STATIC!
  1119.              - An exception from this rule: if you use an animation window
  1120.                _and_ SCROLLING mode, then the non-animation-window-area is
  1121.                covered with the background image from page BACKGNDPAGE, so
  1122.                you may use this routine (and all similiar pixel drawing
  1123.                routines like BackgroundPixel() etc.).
  1124.                If you use the routine for drawing to this area, you MUST
  1125.                use "UpdateOuterArea:=2; Animate;" or a similiar mechanism
  1126.                to make these outer area changes visible!
  1127.              - This routine works with virtual coordinates! - Although this
  1128.                seems silly at first glance (because in STATIC mode, background
  1129.                coordinates are always restricted to (0,0)..(319,199)), it
  1130.                appears to be handy in many situations. If you actually want to
  1131.                address points absolute coordinates (a,b), you can call this
  1132.                routine with coordinates (a+StartVirtualX,b+StartVirtualY)
  1133.                instead.
  1134.              - Because of AniVGA's working scheme, you probably want to call
  1135.                this routine _before_ calling Animate(), so that changes of the
  1136.                point will be visible as soon as possible.
  1137.              - If you are using EMS, ensure the presence of the right EMS-
  1138.                memory block by a
  1139.                "IF EMSused THEN EnsureEMSConsistency(BackgroundEMSHandle)"
  1140.                statement!
  1141.  
  1142. See also   : PutPixel, PagePutPixel, background, coordinates, EMS,
  1143.              How AniVGA works
  1144.  
  1145.  
  1146. BACKX1, BACKX2, BACKY1, BACKY2 - variables
  1147. ──────────────────────────────────────────
  1148.  
  1149. Function   : Hold the background image boundaries in background mode SCROLLING
  1150.  
  1151. Declaration: BackX1,BackY1,BackX2,BackY2:INTEGER;
  1152.  
  1153. Description: When background mode SCROLLING is to be used, you have to define
  1154.              a scrolling area (with SetBackgroundScrollRange()). Due to inter-
  1155.              nal management restrictions of AniVGA, the boundaries of this area
  1156.              must fall on coordinates which are multiples of 16 ("on a grid
  1157.              with mesh 16").
  1158.              If the values you supply don't fulfill this restriction, AniVGA
  1159.              adjusts them automatically to do so and stores them to these
  1160.              variables for further use.
  1161.  
  1162. Note       : The only reason these variables are visible to you are that it
  1163.              could be necessary for you to notice adjustments AniVGA did;
  1164.              so: only read this values, never change them directly!
  1165.              (Look at "background" for an example).
  1166.  
  1167. See also   : background
  1168.  
  1169.  
  1170. BFFFFFFF - utility
  1171. ──────────────────
  1172.  
  1173. Ever had a flat tire? It makes "bffffffffff" as the air goes out and the tire
  1174. becomes smaller and smaller...
  1175. BFFFFFFF is a little compression utility which "lets the air out of your data
  1176. files". Unlike a flat tire, your data files remain functional, however: AniVGA
  1177. has been extended to use some disk reading routines which are "transparent" to
  1178. compressed FNT-, PIC-, PAL-, COD- and LIB-files in that it notes whether the
  1179. file to read in has been compressed with BFFFFFFF or not and acts accordingly.
  1180. You have to supply three command line parameters:
  1181. - the source file name,
  1182. - the destination file name (which must be different from the source)
  1183. - and if you want to (c)ompress or (d)ecompress your file.
  1184. For example...
  1185.  
  1186.  BFFFFFFF mysprite.lib mysprite.new c
  1187.  
  1188. ...would compress the file mysprite.lib to the file mysprite.new! You could
  1189. now delete the old mysprite.lib file and rename mysprite.new to mysprite.lib,
  1190. if you want.
  1191.  
  1192. If you want to create a compressed library, you have several possibilities:
  1193. a) First compress the COD-files and then concatenate them to the LIB-file
  1194. b) First concatenate the (uncompressed) COD-files and then compress this LIB
  1195. c) Concatenate some compressed and not compressed files together to form a
  1196.    library (but you may *NOT* compress that library afterwards!!!)
  1197. d) Build two compressed libraries, using a),b) or c), and then concatenate
  1198.    them to form a new library
  1199. In other words, you may concatenate and/or compress freely, as long as you
  1200. meet one requirement: no file may be compressed more than one time!
  1201. In especially, you may not compress a LIB-file in which one or more COD-files
  1202. have already been compressed beforehand!!!
  1203.  
  1204. The most effective way for compression is b): chain uncompressed COD-files to
  1205. build a library and then compress that library. If you are unsure whether one
  1206. or more of the files within that library have already been compressed in
  1207. before, then use UNLIB on the library (this will result in uncompressed CODs),
  1208. bundle these files again to form a library and then compress it.
  1209.  
  1210. Note : - Using compressed files is a trade off between speed and disk space:
  1211.          compressed files take some time to decompress while loading, but pre-
  1212.          serve disk space, uncompressed files load faster but occupy more disk
  1213.          space.
  1214.        - First, create your program with uncompressed data files. Then, decide
  1215.          if it pays of to compress the files.
  1216.        - All utility files with the exception of BFFFFFFF will produce uncom-
  1217.          pressed data files; you'll have to use BFFFFFFF to compress them.
  1218.        - As said, you may not "double compress" a file; however, BFFFFFFF can
  1219.          care for that automatically with the exception of LIBs (see above)
  1220.        - If you type in the command line to invoke BFFFFFFF, don't count the
  1221.          "F"s, as MSDos will forgive you, if you type in more than necessary:
  1222.          BFFFFFFFFFFFFFFFFFF foobar.cod foobar.new c   will work, too!
  1223.        - See "COMPRESS" below for more information about the compression
  1224.  
  1225.  
  1226. COMPRESS - unit
  1227. ───────────────
  1228.  
  1229. Function   : Provide data compression and decompression routines
  1230.  
  1231. Declaration: Unit Compression;
  1232.  
  1233. Description: AniVGA has been extended to use compression techniques for data
  1234.              storage (COD-, FNT-, LIB-, PIC- and PAL-files). "Compression" is
  1235.              the unit which holds the necessary code to achieve this; techni-
  1236.              cally spoken, it's an implementation of a combined RLE and
  1237.              Huffman algorithm.
  1238.              All data access routines are "transparent" in that they automati-
  1239.              cally detect whether the data file to read in has been compressed
  1240.              or not and act accordingly.
  1241.              This way, it is up to you to decide whether you want to use data
  1242.              compression with your program (which slows down reading in the
  1243.              files but preserves disk space) or not.
  1244.              In my opinion, it is best to first develop your program normally
  1245.              and then afterwards decide _if_ and _which_ files to compress.
  1246.              Compression itself has to be done manually by using BFFFFFFF on
  1247.              the files (see there for more information).
  1248.  
  1249. Note       : - COMPRESS can be used as a stand-alone unit for data compression
  1250.                purposes, of course. Read COMPRESS.DOC for more about that
  1251.              - It is easy to find out, whether a file has been compressed or
  1252.                not: just look at the very first bytes in the file; if they
  1253.                read "HUC" (for: Huffman coded), then it is compressed
  1254.  
  1255. See also   : BFFFFFFF
  1256.  
  1257. CopyVRAMtoVRAM - procedure
  1258. ──────────────────────────
  1259.  
  1260. Function   : Copy video RAM contents using write mode 1
  1261.  
  1262. Declaration: PROCEDURE CopyVRAMtoVRAM(source,dest:POINTER; len:WORD); FAR;
  1263.  
  1264. Description: This is a generic low-level procedure to move video data around.
  1265.              It uses write mode 1 of the VGA card for quick video memory
  1266.              moves and awaits the source and destination addresses in
  1267.              "source" and "dest", respectively. "len" is the length of the
  1268.              block to move in _address bytes_ (in write mode 1, one address
  1269.              bytes stands for four memory bytes).
  1270.  
  1271. Note       : - It became necessary merely for one reason: as the background
  1272.                page has been moved from VRAM to normal RAM (or EMS), commands
  1273.                to load "the background page" now route their data to RAM.
  1274.                To access the *VRAM* area formerly assigned to that page (in
  1275.                the address range $A000:$7D00..$A000:$BB7F), you first have to
  1276.                load data into page 0 or 1 and then move it to that area using
  1277.                CopyVRAMtoVRAM(Ptr($A000,0),Ptr($A000,$7D00),PAGESIZE).
  1278.                This way, that area can be used for storing a picture,
  1279.                presumably for use of IntroScroll()
  1280.              - Because write mode 1 is used, the addresses must lie in the
  1281.                VGA's card address range. On normal VGA-cards, this is the
  1282.                $A000 segment only; some SVGA-cards also enable the $B000
  1283.                for graphic usage, but don't rely upon that!
  1284.              - This routine is "the hacker's toolkit". You are discouraged
  1285.                to use it; maybe it won't be supported in future versions or
  1286.                its interface will change.
  1287.  
  1288. See also   : IntroScroll
  1289.  
  1290.  
  1291. CloseRoutines - procedure
  1292. ─────────────────────────
  1293.  
  1294. Function   : Terminates AniVGA
  1295.  
  1296. Declaration: PROCEDURE CloseRoutines; FAR;
  1297.  
  1298. Description: Calling this routine switches back from AniVGA's special graphic
  1299.              mode into the graphic or text mode previously set.
  1300.  
  1301. Note       : This should always be the last call to a routine of AniVGA in your
  1302.              programs.
  1303.  
  1304. See also   : InitGraph
  1305.  
  1306.  
  1307. COLLISION-DETECTION, CONCAVE, CONVEX - information
  1308. ──────────────────────────────────────────────────
  1309.  
  1310. A graphical figure can be classified by its outline into one of two groups,
  1311. called "concave" or "convex" figures.
  1312. To motivate this mathematical notion >eh, don't get frustrated...<, regard
  1313. your sprite only given by its "outmost" points, which connected together shape
  1314. the figures boundaries.
  1315. The figure is called "convex" :<=> every pair of arbitrarily choosen points
  1316. on this boundary build a line which is totally inside (or at least on the
  1317. boundary of) the figure:
  1318.   ┌──────┐ This rectangle is "convex", because whenever you choose two points
  1319.   │      │ on its boundaries and connect them, the resulting line lies com-
  1320.   └──────┘ pletely inside (or on the boundary) of the rectangle itself.
  1321.  
  1322.   ┌──────┐ On the other hand, this figure would be "concave", because if you
  1323.   └─┐  ┌─┘ choose the top-right and bottom-right corner (say) and connect them,
  1324.   ┌─┘  └─┐ then the middle part of the resulting vertical line lies outside the
  1325.   └──────┘ figure.
  1326.  
  1327. That is (in a very lax form) the _mathematical_ definition of these terms, but
  1328. AniVGA completely deals with either horizontal or vertical lines, so that an
  1329. extension of these terms can be made:
  1330.  
  1331. A sprite is called "horizontal concave" ("vertical concave"), if a horizontal
  1332. (vertical) line connecting two points of the sprite's boundary can be found
  1333. so that parts of this line lies outside the sprite; if the sprite is not hori-
  1334. zontal (vertical concave), it is "horizontal convex" ("vertical convex").
  1335.  
  1336. In that sense, the second of the figures above is "vertical concave", but
  1337. "horizontal convex"!
  1338. (Notice that figures which are concave in the pure _mathematical_ sense are
  1339.  sometimes treated as convex by this definition, as this cross:)
  1340.     ┌─┐     (If you use either a horizontal or vertical "scan line" sweeping
  1341.   ┌─┘ └─┐    throughout the cross, there will be never more than one part of
  1342.   └─┐ ┌─┘    the "scan line" which belongs to the figure; you can use this
  1343.     └─┘      principle as a second definition for horizontal/vertical convex)
  1344.  
  1345. This terminology comes in handy when describing some mechanisms of AniVGA: a
  1346. sprite is drawn LINEwise. For this, every point between the leftmost and right-
  1347. most point of a sprite's line is considered to be an _inner_ point of the
  1348. sprite, thus AniVGA assumes a horizontal convexity! If your sprite isn't, like
  1349. this one...
  1350.   ┌─────┐  ...and the points between the two "legs" of this sprite shall still
  1351.   │ ┌─┐ │  be treated as "transparent" (assuming they have been defined with
  1352.   │ │ │ │  color "black" (=0)), you must use display mode "Display_NORMAL",
  1353.   │ │ │ │  because the "Display_FAST" mode would treat them as belonging to the
  1354.   └─┘ └─┘  sprite itself and draw them as "covering" black.
  1355.  
  1356. (To state it otherwise: whenever your sprite is (at least) horizontal convex
  1357.  and you don't need the feature of transparent parts inside the sprite, you
  1358.  can use the "Display_FAST" mode without any loss of accuracy in the sprite
  1359.  display)
  1360.  
  1361. Tip: the spritemaker program MAKES allows to display a sprite's horizontal
  1362. boundaries, which makes it easier for the beginner to decide about that
  1363. figure's convexity. But whenever you are unsure, you still can use mode
  1364. "Display_NORMAL" for drawing it.
  1365.  
  1366. ---
  1367.  
  1368. Things get a bit more tough when deciding if two sprites collide or not (which
  1369. is an important task): in difference to many sprite toolkits, AniVGA doesn't
  1370. use a "mask" approach, which makes sprites big and collision detection slow.
  1371. Instead, AniVGA uses a sprite's outline to decide whether two sprites collide.
  1372. For that, it computes for every line (column) of the overlap region of the
  1373. sprites' surrounding rectangles, whether the sprites overlap horizontally
  1374. (vertically) and says "collision!" only if there are intersections in both
  1375. directions. In pseudo code:
  1376.  
  1377. IF smallest_box_around(sprite1) doesn't intersect smallest_box_around(sprite2)
  1378.  THEN no_collision
  1379.  ELSE BEGIN
  1380.        compute the lines and columns for which the 2 sprite rectangles overlap
  1381.        FOR every such line compare -with the help of the sprite boundaries- if
  1382.         the corresponding lines overlap
  1383.        FOR every such column do the same check
  1384.        ONLY_IF there is an intersection in at least one line AND one column
  1385.         THEN collision!
  1386.         ELSE no_collision
  1387.       END
  1388.  
  1389. If you think a byte (=8 bits...) about this algorithm, you'll see that it can
  1390. lead to misdetection, in that the algorithm says "collision!", although there
  1391. is none (but it still guarantees that if there _is_ a collision, the alg. will
  1392. detect it) as in the following example:
  1393.           ┌─────┐
  1394.           └───┐ │
  1395.    ┌────────┐ │ │
  1396.    │ ┌────┐ │ │ │
  1397.    │ │ ┌─┐│ │ │ │  <─ In this line there is a "horizontal collision" (that is,
  1398.    └─┘ │ │└─┘ │ │     the two sprites overlap in their horizontal dimension)
  1399.        │ └────┘ │  
  1400.        └────────┘  ┌─ In this column there is a "vertical collision"
  1401.            ^───────┘
  1402.  
  1403. To state things without a proof here, such an (unavoidable) misdetection is
  1404. only possible, if at least one of the two sprites is neither horizontal nor
  1405. vertical convex!!!
  1406.  
  1407. Even then, it takes special constellations (as the one above) to produce such
  1408. an error, so that in praxis, it is very unlikely for such an error to occur.
  1409.  
  1410.  
  1411. Color - variable
  1412. ────────────────
  1413.  
  1414. Function   : Determines the actual drawing color
  1415.  
  1416. Declaration: VAR Color:BYTE;
  1417.  
  1418. Description: Various drawing routines use this global variable to determine
  1419.              which color should be used.
  1420.  
  1421. Note       : AniVGA uses the standard color table of the 256-color mode $13.
  1422.  
  1423. See also   : -
  1424.  
  1425.  
  1426. ColorTable - type
  1427. ─────────────────
  1428.  
  1429. Function   : Supply a data type for self-defined "Shadow Tables"
  1430.  
  1431. Declaration: TYPE ColorTable=ARRAY[0..255] OF BYTE;
  1432.  
  1433. Description: If you want to use a different color look-up-table for your
  1434.              sprites in display mode Display_SHADOW or Display_SHADOWEXACT
  1435.              than can be achieved with SetShadowTab(), you must build a table
  1436.              like this.
  1437.              Each entry gives the color which should be used to replace the
  1438.              original color with that index, i.e.: if c is of type ColorTable
  1439.              and c[5]=9, this means that every point of your sprite which is to
  1440.              be drawn over a pixel with color 5 should replace that pixel with
  1441.              color 9.
  1442.              You can find an example how to activate such a "home-brew" table
  1443.              at "ShadowTab".
  1444.  
  1445. Note       : -
  1446.  
  1447. See also   : ShadowTab, SetShadowTab, Display modes, Palette
  1448.  
  1449.  
  1450. COORDINATES - information
  1451. ─────────────────────────
  1452.  
  1453. AniVGA has to deal with two kinds of coordinates: "virtual" and "absolute" ones.
  1454. An absolute coordinate lies in the range 0..319, 0..199 for the x and y values,
  1455. respectively. It names a unique point on your graphic screen.
  1456. However, AniVGA doesn't restrict animations to take place on the visible
  1457. graphic screen: its routines deal with coordinates in the range -16000..+16000
  1458. in each direction, called "virtual coordinates".
  1459. The picture you view while AniVGA's routines are running is a window of that
  1460. virtual screen, 320 points wide and 200 points high.
  1461. Naturally, the graphic hardware only knows absolute coordinates and thus,
  1462. AniVGA has to transform virtual in absolute coordinates. It does this with the
  1463. help of the two variables StartVirtualX and StartVirtualY which together speci-
  1464. fy the starting point of the upper left corner of your actual screen window;
  1465. e.g. if (StartVirtualX,StartVirtualY) was (1000,2000) then you would look at
  1466. the part of AniVGA's world which consists of the 320x200 region with the coor-
  1467. dinates xε(1000..1319) and yε(2000..2199).
  1468. Note that there is one severe restriction, though: because it is absolutely
  1469. impossible to hold a complete "virtual" screen bitmap for AniVGA's world in
  1470. memory (it would need app. 1GB RAM!), all drawing commands only take place on
  1471. the visible screen.
  1472. This means that you can't draw lines, points or any other objects which are
  1473. _not_ sprites outside the visible window that become visible, when you scroll
  1474. your window over to that part of the virtual screen. For example, if you draw
  1475. a point somewhere outside your visible window (say at (-10000,1234) while your
  1476. visible window starts at (500,900)) and pan to that region afterwards (by set-
  1477. ting (StartVirtualX,StartVirtualY)=(-10100,1200) or something like that), you
  1478. won't see that point: it is stored nowhere.
  1479. (The only way to circumvent this is to define the point as a sprite and set its
  1480.  coordinates (SpriteX[],SpriteY[]) to (-10000,1234), because sprites are the
  1481.  only objects which the system stores!).
  1482.  
  1483. More general:
  1484. Because there is _no_ complete virtual screen, all information drawn outside
  1485. the coordinate range visible at the moment will be lost and all information
  1486. read in from these "offscreen" pixel positions will be zero (= black).
  1487. For that reason it may seem strange for some routines that were restricted in
  1488. their use to the "real" (= absolute coordinate) screen region to use virtual
  1489. coordinates inspite (e.g.: GetImage, BackGroundGetPixel,...), but this was done
  1490. intentionally, because it leaves room for further improvements: if it should be
  1491. possible some day to store a complete virtual screen image, there will be no
  1492. changes necessary in AniVGA's syntax.
  1493. Meanwhile, it is simple to transform absolute and virtual coordinates into each
  1494. other whenever necessary, using the following equivalence:
  1495.  
  1496.   virtual X-coordinates - StartVirtualX = absolute X-coordinates
  1497.   virtual Y-coordinates - StartVirtualY = absolute Y-coordinates
  1498.  
  1499. As a result: virtual coordinates lie in the range -16000..+16000, the start of
  1500. the visible part is defined in StartVirtualX and StartVirtualY and only sprites
  1501. can be "scrolled in" into the visible screen, while all other objects are
  1502. "lost".
  1503.  
  1504.  
  1505. DefaultColors - constant
  1506. ────────────────────────
  1507.  
  1508. Function   : Supplies the default RGB-colors of mode $13 to the user
  1509.  
  1510. Declaration: CONST DefaultColors:Palette=
  1511.              (
  1512.               (red:  0; green:  0; blue:  0),
  1513.                [...stuff deleted...]
  1514.               (red: 63; green: 63; blue: 63)
  1515.              );
  1516.  
  1517. Description: AniVGA and its accompanying utility programs are based on the
  1518.              Bios' default color palette. That ain't necessary, though (and
  1519.              you *can* set different palettes), but it makes things a bit
  1520.              easier!
  1521.              DefaultColors is a listing of these default colors.
  1522.  
  1523. Note       : Consider the table as *read only*! When you use SetPalette(),
  1524.              AniVGA will not temper this table (thus you can use it to restore
  1525.              the original palette values again).
  1526.  
  1527. See also   : Palette, SetPalette, GetPalette
  1528.  
  1529.  
  1530. Display modes - information
  1531. ───────────────────────────
  1532.  
  1533. AniVGA is able to display a sprite in several "modes". This describes how the
  1534. sprite's data should be handled when drawing the sprite to the screen. Up to
  1535. now, there are four modes:
  1536.  - Display_NORMAL  
  1537.  - Display_FAST
  1538.  - Display_SHADOW
  1539.  - Display_SHADOWEXACT
  1540. This mode is linked to a sprite's physical data by creation of the sprite with
  1541. the spritemaker program (and defaults to Display_NORMAL), but can be altered
  1542. once the sprite is loaded into memory with the procedure SetModeByte().
  1543.  
  1544. Note that the display mode information is part of the _physical_ sprites (that
  1545. is, the memory image of the bytes loaded at the beginning), not the _logical_
  1546. sprites (the "handles" in the SpriteN-array to this physical data). For that
  1547. reason, a change of the display mode of a sprite with spriteLOAD number 123
  1548. (say) will affect _all_ sprites of type 123 (= all entries in SpriteN[] with
  1549. value 123). This is intended, because the display mode is a piece of informa-
  1550. tion reflecting the sprite's physical structure!
  1551. (For the case that you disagree: of course you are free to load the same sprite
  1552.  with a different load number into memory a second time and assign another
  1553.  display mode to this copy!)
  1554.  
  1555. In mode "Display_NORMAL" you can think of a sprite as a picture with holes at
  1556. the places where its pixels have color 0: when displayed, all the parts of the
  1557. sprite with color<>0 will cover (paint over) the screens original pixels, but
  1558. the pieces with color=0 will act like "window panes": the original contents of
  1559. the screen remain visible there.
  1560. This mode is useful for all kinds of sprites which have such opaque holes in-
  1561. side themselves: cars/planes/houses or other objects with window panes, but
  1562. also all "concave" sprites. Note that black, COVERING parts must be realized
  1563. with a dark color<>0, for example color 16.
  1564.  
  1565. "Display_FAST" is a bit (but not that dramtically) faster than the last method,
  1566. because it doesn't know of a special color: all sprite data is treated equally
  1567. and stored to the screen at once. For that, all parts of the sprite are
  1568. covering. (But note that a sprite consists only of the points "inside" and on
  1569. its boundaries: all the points "outside" the sprite doesn't matter).
  1570. You will use this mode whenever you have sprites which meet the following re-
  1571. quirements: they are "convex" and don't have any transparent parts inside them-
  1572. selves.
  1573.  
  1574. "Display_SHADOW" is a tribute to the fact that one often needs some kind of
  1575. shadowing to give the impression of an freefloating object or other pseudo
  1576. 3D-effects. In this mode, the sprite's real colors are insignificant, only its
  1577. boundaries and the actual contents of the screen where the sprite shall be
  1578. drawn are important. The color of every sprite point is determined by the color
  1579. of the appropriate screen point. The color of these points are translated by
  1580. the lookup table ShadowTab into darker ones.
  1581. If you want to give a sprite a shadow zone, then you must divide your sprite
  1582. into two ones: one building the sprite itself and a second one to realize only
  1583. that shadow area, and compose them with appropriate coordinates.
  1584.  
  1585. "Display_SHADOWEXACT" behaves quite similiar to "Display_SHADOW", but shadowing
  1586. will only take place at the sprite's pixels with color <>0, that is: color 0
  1587. is again used as "transparent", this time even for shadows! To state it other-
  1588. wise: Display_SHADOWEXACT is for displaying shadows what Display_NORMAL is for
  1589. displaying sprites (and Display_SHADOW relates to Display_FAST in that sense):
  1590. exactly for the same reason, Display_SHADOWEXACT is slower than Display_SHADOW!
  1591. Normally, you will use Display_SHADOW when you are using Display_FAST, too: If
  1592. your sprites are "convex" and don't have any transparent parts inside them-
  1593. selves.
  1594. (If you are still not sure about the difference between these two combinations
  1595.   a) Display_FAST   & Display_SHADOW
  1596.   b) Display_NORMAL & Display_SHADOWEXACT
  1597.  then EXAMPLE3.PAS is a good place to try out!)
  1598.  
  1599. Technically spoken, there are short code areas in AniVGA's routines reserved in
  1600. which the right piece of code to transfer/interpret the sprite's data become
  1601. copied, when not already there. For optimal performance it is wise to group the
  1602. entries in SpriteN[] such that adjacent sprite entries share the same display
  1603. method.
  1604.  
  1605. See also   : convex, concave
  1606.  
  1607.  
  1608. DUMP_SPR - utility
  1609. ──────────────────
  1610.  
  1611. (This is surely a tool for all those hackers among us...)
  1612. If you want to take a closer look at a sprite's data, you don't have to fiddle
  1613. around with DEBUG or the like, just use this sprite dumper: it takes a (binary)
  1614. sprite file (*.COD or *.LIB) and disassembles it into readable ASCII-text.
  1615. You can redirect the output to a file or printer, e.g.:
  1616.  
  1617.  DUMP_SPR mysprite.cod >mysprite.txt
  1618.  
  1619. would dump the sprite file "mysprite.cod" to the ASCII-text file "mysprite.txt"
  1620. for further usage.
  1621. Note that DUMP_SPR creates a format which will be understood by assemblers like
  1622. MASM or TASM so that you can reassemble the files to get a binary sprite file
  1623. once again!
  1624. To do so, you would have to enter the following commands (replace MASM by TASM
  1625. if you use Borland's assembler):
  1626.   MASM mysprite.TXT;                 -> gives you mysprite.OBJ
  1627.   LINK mysprite.OBJ;                 -> gives you mysprite.EXE
  1628.   EXE2BIN mysprite.EXE mysprite.COD  -> gives you mysprite.COD
  1629.  
  1630.  
  1631. EMS - information
  1632. ─────────────────
  1633.  
  1634. Declarations:
  1635.  
  1636. Const EMSInt = $67;   {this is the INT used for the EMS routines}
  1637.       USEEMS = TRUE;  {setting this value to FALSE will prevent AniVGA from }
  1638.                       {using EMS; if you set it to TRUE, it will use EMS if }
  1639.                       {at least 64K are available and its "true" (=hardware)}
  1640.                       {EMS. Otherwise, AniVGA switches to normal RAM auto-  }
  1641.                       {matically}
  1642. Var EMSError:BYTE;    {Any error occuring during a EMS call is reflected by }
  1643.                       {this variable exactly. Of course, the more simple "go}
  1644.                       {no-go" result of any routine using EMS is reflected  }
  1645.                       {in the "Error", too!}
  1646.     BackgroundEMSHandle:WORD; {this is the handle to the allocated EMS block}
  1647.     EMSused:BOOLEAN;  {reflects, if AniVGA really uses EMS: if for some     }
  1648.                       {reason AniVGA denied to use EMS inspite of USEEMS =  }
  1649.                       {TRUE, this variable will be set to FALSE}
  1650. PROCEDURE EnsureEMSConsistency(EMSHandle:WORD);
  1651. {this is the routine to bring in the named EMS block into the EMS page frame}
  1652.  
  1653.  
  1654. Starting with V1.2, the background page has been moved from video memory to
  1655. normal RAM (this results in speed gains on most VGA cards which are unbelie-
  1656. vably slow when accessing VRAM).
  1657. To cut down memory requirements, AniVGA uses 64K EMS memory, if available.
  1658. Now it is possible that you do use EMS memory on your own and therefore some
  1659. precautions have to be taken to avoid interference of the routines. Most of
  1660. them will be handled by AniVGA automatically, but a few remain to your
  1661. responsibility.
  1662. If you already know about how EMS works, just skip the following paragraph:
  1663.  
  1664. EMS is the idea to provide additional memory through an address window of 64K
  1665. (called the "page frame") in a normally unused address space, typically
  1666. $C800:0..$C800:$FFFF or something similiar. A device driver is needed for
  1667. handling EMS and the routines are linked into your system via INT $67.
  1668. These routines are necessary, because if you have 2M (say) of EMS, you must
  1669. tell the hardware somwhow, _which_ 64K out of those 2M shall be "visible" in
  1670. the page frame right now! For this, EMS manages its RAM by so-called "EMS-
  1671. handles": if you allocate an EMS memory block, you get such a handle in
  1672. return. Now each time your software wants to access "its" EMS-memory, it has
  1673. to make sure that this EMS-block is mapped into the page frame --and it does
  1674. so by naming the handle to the EMS-memory.
  1675.  
  1676. It would be pretty easy to ensure the consistency of what we *want* to see
  1677. inside the EMS page frame with what *is* inside it by simply issuing a
  1678. "MapEMSBlockIntoFrame(EMSHandle)"-like command, each time before we start
  1679. accessing any memory cell of the page frame.
  1680. Translated to AniVGA's needs (where only the BACKGNDPAGE's contents have been
  1681. moved to EMS), it would suffice to issue something like...
  1682.  IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle)
  1683. ...whenever we are going to access the background page.
  1684. However, there are situations where this would be a waste of computer
  1685. resources:
  1686.  FOR i:=1 TO 10000 DO
  1687.   BEGIN
  1688.    IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle);
  1689.    PagePutPixel(Random(XMAX+1),Random(YMAX+1),Random(256),BACKGNDPAGE)
  1690.   END;
  1691.  
  1692. Obviously, ensuring the EMS consistency _once_ is enough, as the rest of the
  1693. loop does not change the EMS frame allocation:
  1694.  IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle);
  1695.  FOR i:=1 TO 10000 DO
  1696.   BEGIN
  1697.    PagePutPixel(Random(XMAX+1),Random(YMAX+1),Random(256),BACKGNDPAGE)
  1698.   END;
  1699.  
  1700. Its for this reason only that the above call to EnsureEMSConsistency()
  1701. doesn't have been moved to the BackgroundPutPixel() and BackgroundGetPixel()
  1702. routines! (All the other routines accessing the background page do this
  1703. automatically, as the overhead of the call doesn't matter much, anyway).
  1704.  
  1705. Stated otherwise:
  1706.  
  1707. !! WHENEVER YOU ARE GOING TO USE Background{Put|Get}Pixel()_AND_ YOU HAVE
  1708. !! REASON THAT THE EMS-PAGEFRAME NEEDS UPDATING, ISSUE THE COMMAND
  1709. !! "IF EMSused THEN EnsureEMSConsistency(BackgndEMSHandle)" FIRST!
  1710.  
  1711. See also   : BackgroundGetPixel, BackgroundPutPixel
  1712.  
  1713.  
  1714. EnsureEMSConsistency - procedure
  1715. ────────────────────────────────
  1716.  
  1717. Function   : Brings the contents of the named EMS memory block into the EMS
  1718.              page frame
  1719.  
  1720. Declaration: PROCEDURE EnsureEMSConsistency(EMSHandle:WORD); FAR;
  1721.  
  1722. Description: The routine calls the EMS handler to assure that the EMS memory
  1723.              block pointed to by the given handle is placed into the EMS
  1724.              page frame.
  1725.  
  1726. Note (!)   : - A direct call to this routine will be necessary only for the
  1727.                BackgroundGetPixel() and BackgroundPutPixel() routines
  1728.              - Don't call the routine if you are _not_ using EMS! Use a
  1729.                statement like...
  1730.                IF EMSused THEN EnsureEMSConsistency(BackgroundEMSHandle)
  1731.  
  1732. See also   : EMS
  1733.  
  1734.  
  1735. ERROR - variable
  1736. ────────────────
  1737.  
  1738. Function   : Holds the code of the last error which occured
  1739.  
  1740. Declaration: VAR ERROR:BYTE
  1741.  
  1742. Description: If an error occurs while executing one of its routines, AniVGA
  1743.              terminates that routine and sets ERROR accordingly to reflect that
  1744.              error.
  1745.              You can use GetErrorMessage() anytime to get more information,
  1746.              which error occured.
  1747.              It is your responsibility to check if such an error occured and
  1748.              react in an appropriate way.
  1749.              For the possible values and their descriptions returned by
  1750.              GetErrorMessage, see there.
  1751.              
  1752. Note (!)   : - After processing an error, you have to reset the variable back
  1753.                to Err_None yourself
  1754.              - In respect of future extensions, you should treat every value
  1755.                <> Err_None as an error
  1756.              - The most frequented routine Animate() doesn't produce any
  1757.                errors, neither do several other procedures. As a basic rule,
  1758.                all routines which have to do with file I/O have to be checked.
  1759.              - ERROR is initialized with Err_None
  1760.  
  1761. See also   : GetErrorMessage, InitRoutines
  1762.  
  1763.  
  1764. FadeIn - procedure
  1765. ──────────────────
  1766.  
  1767. Function   : Fade in a graphic page onto the actually visible page.
  1768.  
  1769. Declaration:  PROCEDURE FadeIn(pa,ti,style:WORD); FAR;
  1770.  
  1771. Description: If you need an interesting opening sequence for your program, then
  1772.              FadeIn() is what you need: there are a lot of different routines
  1773.              available to copy one image to the actually displayed graphic page
  1774.              (1-PAGE): supply the page which shall be displayed "pa" (most
  1775.              often, this will be BACKGNDPAGE), "ti" is the time (in millise-
  1776.              conds) the fade should last (approximately), "style" defines the
  1777.              algorithm to be used and must be one of:
  1778.               Fade_Squares,
  1779.               Fade_Circles,
  1780.               Fade_Moiree1 .. Fade_Moiree15,
  1781.               Fade_SweepInFromTop,    Fade_SweepInFromBottom,
  1782.               Fade_SweepInFromLeft,   Fade_SweepInFromRight,
  1783.               Fade_ScrollInFromTop,   Fade_ScrollInFromBottom,
  1784.               Fade_ScrollInFromLeft,  Fade_ScrollInFromRight
  1785.  
  1786. Note       : - The easiest way to use this routine is the following:
  1787.                a) initialize the graphic mode via InitGraph(),
  1788.                b) load the background page BACKGNDPAGE with your normal
  1789.                   animation background,
  1790.                c) (if you want:) fill the visible page 1-PAGE with whatever
  1791.                   you want (initially, it is completely black)
  1792.                d) call FadeIn(BACKGNDPAGE,2000,Fade_???);
  1793.                   (about 2000..4000 milliseconds are good values)
  1794.                e) continue with your normal program
  1795.              - Naturally, AniVGA can't make your PC faster than it is: the
  1796.                time value you supply is a _lower bound_!
  1797.              - FadeIn() will use the "normal" MSDos-timer values for its
  1798.                operation; as this timer has resolution of about 55msec, it
  1799.                is quite inaccurate (..for a computer, I mean..), but as we
  1800.                are talking about thousands of milliseconds here, that won't
  1801.                matter! (Besides that, this timer won't interfere with the
  1802.                one used for the animation rate, set by SetCycleTime()!)
  1803.  
  1804. See also   : -
  1805.  
  1806.  
  1807. FadeToPalette - procedure
  1808. ─────────────────────────
  1809.  
  1810. Function   : Fades the screen from the actual color to another palette
  1811.  
  1812. Declaration: PROCEDURE FadeToPalette(destPal:Palette; AnzSteps:WORD); FAR;
  1813.  
  1814. Description: You have often seen that: a screen becomes slowly dark and when
  1815.              it returns, another image is displayed. This and other effects
  1816.              can be generated by fading a palette to another.
  1817.              "destPal" is the destination palette to which the program will
  1818.              fade (and "ActualColors" holds the starting colors, of course).
  1819.              "AnzSteps" is the number of steps which the routine will
  1820.              generate between the color values of the two palettes.
  1821.              On return, "ActualColors" ( = the actually displayed color
  1822.              palette) has been set to "destPal".
  1823.              For example, a sequence like the following
  1824.  
  1825.                oldPal:=ActualColors;
  1826.                FillChar(tempPal,SizeOf(tempPal),0);
  1827.                FadeToPalette(tempPal,200);
  1828.                [...]
  1829.                FadeToPalette(oldPal,200);
  1830.  
  1831.              would fade the actual screen display to black and afterwards
  1832.              fade it back to the previously set colors again.
  1833.  
  1834. Note       : - Each incremental change of the palette will be synchronized
  1835.                to the vertical retrace signal of the VGA card. This way,
  1836.                "snowy" displays are avoided. As a side effect, each such
  1837.                step takes app. 1/70 sec. In the example above, the fades
  1838.                would take 200/70 sec, each.
  1839.  
  1840. See also   : ActualColors, SetPalette, FadeIn
  1841.  
  1842.  
  1843.  
  1844. FillBackground - procedure
  1845. ──────────────────────────
  1846.  
  1847. Function   : Fills the background page with the specified color.
  1848.  
  1849. Declaration: PROCEDURE FillBackground(color:BYTE); FAR;
  1850.  
  1851. Description: The given value is written into the whole graphic page BACKGNDPAGE
  1852.              and thus defines the picture before all animations take place to
  1853.              have one color.
  1854.  
  1855. Note       : Use of this routine only makes sense when using background mode
  1856.              STATIC!
  1857.  
  1858. See also   : Background, BACKGNDPAGE, BACKGNDADR, GetBackgroundFromPage,
  1859.              LoadBackgroundPage
  1860.  
  1861.  
  1862. FillPage - procedure
  1863. ────────────────────
  1864.  
  1865. Function   : Fills a graphic page completely with a given color
  1866.  
  1867. Declaration: PROCEDURE FillPage(pa:WORD; color:Byte); FAR;
  1868.  
  1869. Description: If you want to paint a complete page uniformly with one color,
  1870.              then this will be the fastest method to do it: specify the graphic
  1871.              page (0, 1, BACKGNDPAGE (=2) or SCROLLPAGE (=3)) in "pa" and the
  1872.              color to be used in "color".
  1873.  
  1874. Note       : - Although possible, you are strongly discouraged to use this pro-
  1875.                cedure in background mode SCROLLING (i.e.: pa=SCROLLPAGE (=3) as
  1876.                page number), because the background is treated completely dif-
  1877.                ferent!
  1878.              - Remember also that changes to one of the drawing pages (0 or 1)
  1879.                have to be applied _after_ calling Animate and will be visible
  1880.                for exactly one animation cycle, whereas changes to the back-
  1881.                ground page remain permanent (and are best done _before_ calling
  1882.                Animate, although that's not peremptory).
  1883.              - This routine is great to produce "flashing" screens: apply it to
  1884.                1-PAGE (the visible page).
  1885.              - Possible ERROR-value returned is Err_InvalidPageNumber
  1886.  
  1887. See also   : background, How AniVGA works, LoadPage, LoadBackgroundPage,
  1888.              GetBackgroundFromPage
  1889.  
  1890.  
  1891. FindFile - function
  1892. ───────────────────
  1893.  
  1894. Function   : Completes the path-part of a given file name
  1895.  
  1896. Declaration: FUNCTION FindFile(P:PathStr):PathStr; FAR;
  1897.  
  1898. Description: This routine expects a normal MSDos file name and looks if there
  1899.              exists a file with this name. If not, all subdirectories under
  1900.              the specified directory are scanned through recursively. If the
  1901.              file still can't be located by that search, the empty string will
  1902.              be returned as the result, otherwise the extended path name of
  1903.              the file is returned.
  1904.              For example, if you P = "C:\TEST\MY_FONT.FON", but the correct
  1905.              directory would be "C:\TEST\FONTS\MY_FONT.FON", then the routine
  1906.              will return the latter path as the result.
  1907.              This routine is handy when loading data files: if your users
  1908.              forget to create a proper subdirectory structure and copy all
  1909.              files into one directory (say C:\ABC\ instead of C:\ABC\BIN\,
  1910.              C:\ABC\FONTS\ and C:\ABC\GRAPHIC\), then your program will still
  1911.              run if it loads its files by only referencing the top level dir:
  1912.              C:\ABC\file.ext will locate the file, no matter in which subdir
  1913.              it really is.
  1914.  
  1915. Note       : - You don't have to use this routine for any of AniVGA's Load* -
  1916.                routines: they use FindFile() automatically! (The routine has
  1917.                been moved to the interface section of the unit, because it
  1918.                may be useful for locating other files, too)
  1919.              - In the Load* - routines of AniVGA, the function is used in that
  1920.                way: first, the file is searched under the given name; if it
  1921.                couldn't be found, all subdirectories of the specified dir are
  1922.                scanned with FindFile(). After that, a normal Dos-operation to
  1923.                open the file is issued (so that programs like APPEND may get
  1924.                their chance, too).
  1925.  
  1926. See also   : -
  1927.  
  1928.  
  1929. Font (*.FNT) files - information
  1930. ────────────────────────────────
  1931.  
  1932. There are two types of font files: monochrome and colored fonts. The first
  1933. ones are encoded as an array of bits, while the latter ones are stored as an
  1934. array of bytes, specifying the colors of each point.
  1935. A font file consists of a six byte header:
  1936. - the tag "FNT", showing that this is a font file
  1937. - the width  of the chars in pixel (1..MaxFontWidth),  that is: 1..15
  1938. - the height of the chars in pixel (1..MaxFontheight), that is: 1..16
  1939. Then follows the data itself; if it is a monochrome font, then each character
  1940. is encoded as a sequence of font height bytes or words, if its width is at most
  1941. 8 pixels or 9..15 pixels, respectively. If it is a colored font, then each
  1942. character is stored as font height times font width bytes.
  1943. The storage order is the same: if you look at an character as a two-dimensio-
  1944. nal array, then each char is stored by storing its pixels row-wise, from top
  1945. to bottom and each row from left to right.
  1946. If the font is proportional spaced, then another 256 byte junk follows, which
  1947. specifies the width of each of the 256 ASCII characters.
  1948. When reading in the data from disk, the font is brought back into a more
  1949. easily two-dimensional standard form for faster access; the necessary memory
  1950. is allocated on the heap: 256*MaxFontHeight*SizeOf(Word)=8K for a monochrome
  1951. font, 256*MaxFontHeight*MaxFontWidth=60K for a colored font.
  1952.  
  1953. Note       : - There are a lot of monochrome font examples, taken from Michael
  1954.                J. Mefford's "FontEdit V1.0" in PC Magazine (Thanks, Joy!)
  1955.                Note that most of these fonts aren't fully compatible with
  1956.                IBM's "8 bit ASCII"!
  1957.              - I added one multi colored font "FIRE.FNT". You have to load and
  1958.                activate the palette "FIRE.PAL" prior to the use of this font
  1959.                (FYI: it uses colors 0, 26 and 240..255)
  1960.  
  1961.  
  1962. FontOrient, FontHeight, FontWidth, FontType, FontWidthTable, FontProportion
  1963. ────────────────────────────────────────────────────────────────────────────
  1964.  - type/constants
  1965. ─────────────────
  1966.  
  1967. Function   : Supply some additional data about the actual font
  1968.  
  1969. Declaration: TYPE  FontOrient=(horizontal,vertical);
  1970.              VAR   FontHeight,FontWidth,FontType,FontProportion :BYTE;
  1971.                    FontWidthTable:ARRAY[0..255] OF BYTE;
  1972.  
  1973. Description: The fonts used for displaying graphic text (OutTextXY(),
  1974.              BackgroundOutTextXY()) can be displayed either horizontally or
  1975.              vertically; use of the TYPE FontOrient simplifies that.
  1976.              To compute the width/height of a text, the constants FontHeight
  1977.              and FontWidth can be used, which specify the size of one letter;
  1978.              however, if your font is proportional, then you should use the
  1979.              function OutTextLength() to compute a string's width.
  1980.              Depending on the font, FontHeightε[1..MaxFontHeight] and
  1981.              FontWidthε[1..MaxFontWidth], where MaxFontHeight=16 and
  1982.              MaxFontWidth=15 (f-i-f-t-e-e-n).
  1983.              FontType specifies, whether the actual font is a monochrome
  1984.              font (FontType=TagMonoFont) or if it's a colored font (FontType=
  1985.              TagColorFont).
  1986.              If FontProportion=TagProportional then the actual font is pro-
  1987.              portional spaced. In this case, the width of each character is
  1988.              stored in the array FontWidthTable[] and you should use
  1989.              OutTextLength() to compute the width of a complete string.
  1990.  
  1991. Note       : - There is no such thing as "FontHeightTable[]": proportional
  1992.                fonts are proportional spaced only in the x-direction
  1993.              - For simplicity, FontWidthTable[i] *always* holds the width of
  1994.                ASCII-char #i, even if the actual font is _not_ proportional.
  1995.                In that case, the table is completely filled with FontWidth.
  1996.              - If your font is proportionl, then FontWidth holds the size of
  1997.                a char-cell as it is _loaded_ from disk. In most cases this
  1998.                is the maximum width an ASCII character may have at all.
  1999.  
  2000. See also   : OutTextXY, BackgroundOutTextXY, OutTextLength, Font files
  2001.  
  2002.  
  2003. FreeImageMem - procedure
  2004. ────────────────────────
  2005.  
  2006. Function   : Releases the memory allocated by a GetImage()-call
  2007.  
  2008. Declaration: PROCEDURE FreeImageMem(p:POINTER); FAR;
  2009.  
  2010. Description: If you use GetImage(), AniVGA allocates the memory needed and
  2011.              returns a pointer to that area, which you can use with PutImage()
  2012.              as often as you desire. If you don't need that clipped image any
  2013.              longer, you should release its memory so that it can be used by
  2014.              other routines again. To do that, just call FreeImageMem() with
  2015.              the pointer GetImage() returned to you.
  2016.  
  2017. Note       : It is this reason -releasing memory- why you shouldn't make an
  2018.              "anonymous" GetImage() / PutImage() combination like
  2019.               PutImage(x,y,GetImage(x1,y1,x2,y2,1-PAGE),1-PAGE): you don't get
  2020.              a handle which could be used to free the occupied memory!
  2021.              Of course, you could use "Mark()" and "Release()", but a simple
  2022.              additional pointer variable ("p") is better style:
  2023.               p:=GetImage(x1,y1,x2,y2,1-PAGE);
  2024.               PutImage(x,y,p,1-PAGE);
  2025.               FreeImageMem(p)
  2026.  
  2027. See also   : GetImage, PutImage
  2028.  
  2029.  
  2030. FreeSpriteMem - procedure
  2031. ─────────────────────────
  2032.  
  2033. Function   : Releases the memory allocated by a LoadSprite()-call
  2034.  
  2035. Declaration: PROCEDURE FreeSpriteMem(number:WORD); FAR;
  2036.  
  2037. Description: This procedure is used to "unload" a sprite from memory.
  2038.              "number" is the sprite's LOADnumber to wipe out from memory.
  2039.  
  2040. Note       : - You don't need to call this routine to overwrite a sprite
  2041.                (that is: call LoadSprite() a 2nd time with the same sprite
  2042.                LOADnumber); AniVGA will do that for you automatically, so
  2043.                there is little need to call this routine manually
  2044.              - Possible ERROR values returned are Err_InvalidSpriteLoadNumber
  2045.  
  2046. See also   : LoadSprite
  2047.  
  2048.  
  2049. GetBackgroundFromPage - procedure
  2050. ─────────────────────────────────
  2051.  
  2052. Function   : Take over one of the drawing pages as background image
  2053.  
  2054. Declaration: PROCEDURE GetBackgroundFromPage(pa:WORD); FAR;
  2055.  
  2056. Description: Specify the graphic page (0 or 1) from which the image should be
  2057.              "captured" and the routine will copy its contents into the back-
  2058.              ground page BACKGNDPAGE (=2) as new background image.
  2059.  
  2060. Note       : - Use of the routine only makes sense if STATIC is used as
  2061.                background mode.
  2062.              - Possible ERROR-values returned are Err_InvalidPageNumber
  2063.  
  2064. See also   : LoadBackgroundPage
  2065.  
  2066.  
  2067. GetErrorMessage - function
  2068. ──────────────────────────
  2069.  
  2070. Function   : Returns a description of the last error occured
  2071.  
  2072. Declaration: FUNCTION GetErrorMessage:STRING; FAR;
  2073.  
  2074. Description: Although you can use the ERROR variable directly to evaluate any
  2075.              error and inform the user about it, it is often more comfortable
  2076.              to let AniVGA do that: GetErrorMessage will give you a string
  2077.              describing the last error which occured in words.
  2078.              The possible string contents and the corresponding ERROR values
  2079.              are:
  2080.  
  2081.               Err_None: 'No Error'
  2082.                No error occured during the routine; this is the variable's
  2083.                initial value
  2084.  
  2085.               Err_NotEnoughMemory: 'Not enough memory available on heap'
  2086.                The program couldn't load sprites or other data to the heap
  2087.  
  2088.               Err_FileIO: 'I/O-error with file'
  2089.                There was an error reading the file; either the file doesn't
  2090.                exist at the path given or it is damaged. Another possibility
  2091.                is that you compressed your file in a wrong way.
  2092.  
  2093.               Err_InvalidSpriteNumber: 'Invalid sprite number used'
  2094.                This error occurs if you try to load a sprite with a sprite
  2095.                loadnumber not in the valid range 1..LoadMAX
  2096.  
  2097.               Err_NoSprite: 'No (or corrupted) sprite file'
  2098.                While attempting to interpret the data just read in, AniVGA
  2099.                found the data not to be in the expected format; either because
  2100.                you used a wrong data file or it is damaged or compressed wrong.
  2101.  
  2102.               Err_InvalidPageNumber: 'Invalid page number used'
  2103.                There are four graphic pages, numbered 0..3. Page 0 & 1 are
  2104.                used for the animation itself, page 2 ("BACKGNDPAGE") holds the
  2105.                static background image and page 3 ("SCROLLPAGE") is reserved
  2106.                for the scrollable background information
  2107.  
  2108.               Err_NoVGA: 'No VGA-card found'
  2109.                The animation package needs a VGA (or compatible) graphic card
  2110.                but couldn't find one
  2111.  
  2112.               Err_NoPicture: 'No (or corrupted) picture file'
  2113.                The background picture file AniVGA should load has not the ex-
  2114.                pected size/format or a DOS-error occured while attempting to
  2115.                access the data
  2116.  
  2117.               Err_InvalidPercentage: 'Percentage value must be 0..100'
  2118.                If you set the colortable for the shadowing effects of sprite
  2119.                display mode Display_SHADOW or Display_SHADOWEXACT, you must use
  2120.                a percentage value giving the remaining brightness of the colors
  2121.                in the shadow areas, which must be in the range 0..100%, of
  2122.                course
  2123.  
  2124.               Err_NoTile: 'No (or corrupted) tile/sprite file'
  2125.                There was an error loading the specified sprite file(s) and
  2126.                interpreting them as background tiles. Most often this occurs
  2127.                because the sprite doesn't meet the requirement to be a multiple
  2128.                of 16 points in its x- and y-directions!
  2129.  
  2130.               Err_InvalidTileNumber: 'Invalid tile number used'
  2131.                There may be only 256 background tiles, numbered 0..255
  2132.  
  2133.               Err_InvalidCoordinates: 'Invalid coordinates used'
  2134.                The virtual background coordinates you use must lie in the range
  2135.                (BackX1,BackY1)..(BackX2,BackY2), which has been specified with
  2136.                SetBackgroundScrollRange()
  2137.  
  2138.               Err_BackgroundToBig: 'Background to big for tile-buffer'
  2139.                AniVGA's tile buffer can hold no more than MaxTiles (=10000)
  2140.                tiles, that is an area of 10000*16*16 pixels². Check the area
  2141.                you specified in your SetBackgroundScrollRange()-call!
  2142.  
  2143.               Err_InvalidMode: 'Only STATIC or SCROLLING allowed here'
  2144.                The only background modes AniVGA knows are STATIC and SCROLLING
  2145.  
  2146.               Err_InvalidSpriteLoadNumber: 'Invalid spriteload number used'
  2147.                spriteLOADNumbers must lie in the range 0..LoadMAX; when you
  2148.                get this error, you probably confounded a spriteLOADnumber with
  2149.                a spritenumber
  2150.  
  2151.               Err_NoPalette: 'No (or corrupted) palette file'
  2152.                You tried to load a palette file which didn't meet the require-
  2153.                ments: a palette file must be of size 3..768 bytes and a
  2154.                multiple of 3
  2155.  
  2156.               Err_PaletteWontFit: 'Attempt to write beyond palette end'
  2157.                While attempting to read in and store the palette file into the
  2158.                actual color table, AniVGA noticed that it would have to write
  2159.                beyond the end of that table; decrease your "number" parameter!
  2160.  
  2161.               Err_InvalidFade: 'Invalid fade style used'
  2162.                You tried to use a fade style not supported by the unit: look
  2163.                at routine "FadeIn()" for allowed styles.
  2164.  
  2165.               Err_NoFont: 'No (or corrupted) font file'
  2166.                While attempting to interpret the data just read in, AniVGA
  2167.                found the data not to be in the expected format; either because
  2168.                you used a wrong data file or it is damaged or compressed wrong.
  2169.  
  2170.               Err_EMSError: 'Problems with EMS memory'
  2171.                Some error occured while accessing a EMS routine; you can use
  2172.                EMSError to analyze the the error more exactly.
  2173.  
  2174.               (else): 'Unknown error'
  2175.                If ERROR has none of the above values, this string will be
  2176.                returned; this should never happen, though.
  2177.  
  2178. Note       : Calling GetErrorMessage won't set back the ERROR variable either;
  2179.              you must do that explicitly!
  2180.  
  2181. See also   : ERROR
  2182.  
  2183.  
  2184. GetImage - function
  2185. ───────────────────
  2186.  
  2187. Function   : Makes a copy of the specified screen region
  2188.  
  2189. Declaration: FUNCTION GetImage(x1,y1,x2,y2:INTEGER;pa:WORD):POINTER; FAR;
  2190.  
  2191. Description: - This function works much the same as its equivalent in Turbo-
  2192.                Pascal: (x1,y1) and (x2,y2) define the upper left and lower right
  2193.                corners of the screen part to save, but now these coordinates are
  2194.                _virtual coordinates_, the routine reserves the memory needed to
  2195.                hold the copy itself and you can specify the graphic page, from
  2196.                which the image is to be taken (pa=0, 1, BACKGNDPAGE (=2) or
  2197.                SCROLLPAGE (=3) ).
  2198.              - As result you get a pointer to the start of the saved image,
  2199.                which can be used with PutImage().
  2200.              - If there is not enough memory available or the specified part of
  2201.                the screen lies completely outside the visible screen, NIL is
  2202.                returned.
  2203.              - Besides that, there are 5 global variables which are set accor-
  2204.                dingly:
  2205.                was_cut:BOOLEAN = TRUE/FALSE, if the image had to be _partially_
  2206.                        clipped (if the specified image is totally offscreen,
  2207.                        was_cut stays at FALSE!)
  2208.                left_cut, right_cut, top_cut, bottom_cut:WORD  hold the size how
  2209.                        much had to be clipped off at the boundaries; these
  2210.                        values are only set when was_cut=TRUE
  2211.                (If you wonder about this odd definitions: GetImage was intended
  2212.                 to work only with the visible screen (that is: with _absolute_
  2213.                 coordinates): together with its counterpart PutImage(), you can
  2214.                 copy a part of the screen to another part or page. In that case,
  2215.                 you do not have to fiddle around with clipping: just issue a
  2216.                 GetImage() and use PutImage() to paste this block elsewhere.
  2217.                 But there may be some applications, when you cut out part of
  2218.                 the screen and think you got the complete graphic figure you
  2219.                 wanted, although (because of the use of virtual coordinates and
  2220.                 your figure being partially offscreen) you got only part of it.
  2221.                 Checking "was_cut" informs you about such a partial clipping.
  2222.                 If your figure is completely offscreen, that is a special case:
  2223.                 it depends on your application whether this should be treated
  2224.                 as being okay or not; if you need special treatment (as with
  2225.                 partial clipping), you still can check for this with something
  2226.                 like:
  2227.                 ...
  2228.                 image_ptr:=GetImage(x1,y1,x2,y2,1-PAGE); {1-PAGE=visible page!}
  2229.                 IF ERROR<>Err_None
  2230.                  THEN ... {probably not enough memory}
  2231.                  ELSE IF (was_cut) OR (image_ptr=NIL)
  2232.                        THEN ... {partial or total clipping occured}
  2233.                        ELSE ... {no clipping at all}
  2234.                )
  2235.              - possible ERROR-values returned are: Err_NotEnoughMemory and
  2236.                Err_InvalidPageNumber
  2237.  
  2238. Note       : - As already mentioned, GetImage() only works on screen regions in
  2239.                the _absolute_ coordinate range 0..319, 0..199, but expects
  2240.                _virtual_ coordinates!
  2241.              - To release the memory allocated by a GetImage() call, you must
  2242.                use FreeImageMem(); TurboPascal's "Dispose()" won't work.
  2243.  
  2244. See also   : PutImage, FreeImageMem, coordinates
  2245.  
  2246.  
  2247. GetModeByte - function
  2248. ──────────────────────
  2249.  
  2250. Function   : Returns the actual display method set for a sprite
  2251.  
  2252. Declaration: FUNCTION GetModeByte(Sp:WORD):BYTE; FAR;
  2253.  
  2254. Description: "Sp" specifies the spriteLOADnumber of the sprite from which the
  2255.              user wants to know the display mode. The function will return one
  2256.              of the valid modes Display_NORMAL, Display_FAST, Display_SHADOW
  2257.              or Display_SHADOWEXACT.
  2258.  
  2259. Note       : - Again, spriteLOADnumbers are used!
  2260.              - If the LOADnumber given doesn't exist (because no sprite has
  2261.                been loaded with that number), the routine will return
  2262.                Display_UNKNOWN instead.
  2263.  
  2264. See also   : Display modes, SetModeByte
  2265.  
  2266.  
  2267. GetPalette - procedure
  2268. ──────────────────────
  2269.  
  2270. Function   : Reads out the actually set color palette directly from the VGA
  2271.  
  2272. Declaration: PROCEDURE GetPalette(VAR pal:Palette); FAR;
  2273.  
  2274. Description: "pal" specifies the variable in which to store the actual palette.
  2275.  
  2276. Note (!)   : - This procedure has been added for completeness, merely: As long
  2277.                as you make all palette changes by using SetPalette(), you can
  2278.                use the variable "ActualColors[]" instead!
  2279.              - You must be in graphic mode already or you will get rubbish!
  2280.                To state in otherwise: call this routine _after_ having called
  2281.                InitGraph() and _before_ calling CloseRoutines()!
  2282.  
  2283. See also   : SetPalette, Palette, ActualColors
  2284.  
  2285.  
  2286. GetPixel - function
  2287. ───────────────────
  2288.  
  2289. Function   : Reads a pixel's color
  2290.  
  2291. Declaration: FUNCTION GetPixel(x,y:INTEGER):BYTE; FAR;
  2292.  
  2293. Description: Returns the color value of the specified pixel with the virtual
  2294.              coordinates (x,y) on graphic page PAGE. If (x,y) lies offscreen
  2295.              (to be precise: the computed absolute coordinates lie offscreen),
  2296.              then zero (= black) is returned.
  2297.  
  2298. Note       : Be aware that PAGE is the invisible page, not the one you are
  2299.              looking at!
  2300.  
  2301. See also   : coordinates, PAGE, PageGetPixel, PutPixel
  2302.  
  2303.  
  2304. GetSplitIndex - function
  2305. ────────────────────────
  2306.  
  2307. Function   : Determine which sprites will be clipped to the animation window
  2308.  
  2309. Declaration: FUNCTION GetSplitIndex:INTEGER; FAR;
  2310.  
  2311. Description: If you used SetSplitIndex() to enable that some sprites may be
  2312.              drawn outside the animation window, you may use this routine to
  2313.              determine which sprites will be clipped and which won't:
  2314.              If "n" is the value returned, then this means that...
  2315.              SPRITE[0..n]       (if active) will not be clipped while
  2316.              SPRITE[n+1..NMAX]  will
  2317.              A return value of "-1" means that all sprites will be clipped;
  2318.              this is the default value at start-up.
  2319.  
  2320. Notes      : -
  2321.  
  2322. See also   : SetAnimateWindow, WinClip
  2323.  
  2324.  
  2325. GetTile - function
  2326. ──────────────────
  2327.  
  2328. Function   : Compute which tile is at a given point
  2329.  
  2330. Declaration: FUNCTION GetTile(x,y:INTEGER):BYTE; FAR;
  2331.  
  2332. Description: When using SCROLLING background mode, you can use PutTile() to
  2333.              link a background tile to a special coordinate. GetTile() is
  2334.              the opposite to that: you supply a point (x,y) to it and the
  2335.              function returns which tile has been pasted at this corrdinate
  2336.              previously.
  2337.  
  2338. Notes      : If the point (x,y) lies outside of the scroll range which you
  2339.              had defined by calling SetBackgroundScrollRange() previously,
  2340.              then the routine will return the number of the offscreen tile
  2341.              (which you may set by SetOffscreenTile() ).
  2342.  
  2343. See also   : background, tile, SetBackgroundScrollRange, coordinate, BackX1,
  2344.              BackX2, BackY1, BackY2, PutTile
  2345.  
  2346.  
  2347. GRAB - utility
  2348. ──────────────
  2349.  
  2350. GRAB allows you to "steal" graphics from other applications and convert them
  2351. into sprite files (*.COD) or background images (*.PIC) for use with AniVGA.
  2352. This program is a terminate-and-stay-resident (TSR) utility that has to be run
  2353. before starting those applications from which you want to capture graphic
  2354. images.
  2355. It requires a mouse to be installed and a VGA card - note that an EGA won't do!
  2356. Pressing the hotkey CTRL-ALT-G will popup a frame which you can move and resize
  2357. to select the part of the graphic sreen you want to save (if you are not in a
  2358. graphic mode or in a graphic mode unknown to GRAB you'll here a beep instead).
  2359. Note that if you are in a "MSDos critical" situation, GRAB can't pop up.
  2360. Use the mouse to move the box, hold down the left mouse button and drag the
  2361. mouse to resize the box (in "sprite mode" only). The space bar will toggle
  2362. between "sprite mode" and "background mode", pressing the right button will
  2363. store the framed graphic to disk (either as sprite or background image, what-
  2364. ever program mode you are actually in).
  2365. Press ESC (or both mouse buttons simultaneously) anytime to escape from GRAB
  2366. back to your application.
  2367. By default, GRAB starts in sprite capture mode, thus generating sprite files
  2368. (starting with the file name GRAB_000.COD with increasing numbers for the next
  2369. sprites). To get a background image, toggle into screen capture mode by pres-
  2370. sing the space bar (a second press will switch back to sprite capture mode
  2371. again), select the screen region wanted and press the right mouse button to
  2372. get that part of the screen in the file GRAB_000.PIC (or whatever number is
  2373. actual then).
  2374. In both modes, GRAB also dumps the actually set palette to disk, having the
  2375. same number as the COD/PIC file, but with the ending ".PAL" and a (P)icture
  2376. or (S)prite replacing the underscore, e.g. "GRABS000.PAL" for the first
  2377. sprite saved.
  2378. Naturally, you can't resize your frame in the screen capture mode: it stays at
  2379. its initial size of 320x200 points.
  2380. Note that there is the a restriction for a sprite's size: a sprite may be
  2381. 152x152 points in max., if you need bigger sprites then just save the sprite
  2382. as a PIC file and convert it afterwards, using MAKES.
  2383.  
  2384. There is only one possible command line parameter when installing GRAB:
  2385. "BIOS": Supplying "BIOS" tells GRAB to use the video bios interrupt INT10h to
  2386. access all video data. This should work on almost every VGA, but is extremely
  2387. slow.
  2388. Otherwise, GRAB defaults to its internal, fast access routines. Note that some
  2389. applications directly reprogram the VGA hardware so that GRAB must fail on
  2390. them (both in default and BIOS mode)!
  2391.  
  2392. Note       :
  2393.  - It may happen that you can't popup GRAB in some applications; if you have
  2394.    some commercial screen capture utility, you can use that (most often, they
  2395.    are more "radical" in their behaviour, using undocumented Dos-funtions and
  2396.    the like).
  2397.    Then, use an appropriate viewer program and capture the graphic from their
  2398.    display!
  2399.    (Sorry, I know there are much situations where GRAB _should_ popup, but
  2400.     does not - I'm not content with that, either, but I didn't write the TSR-
  2401.     unit, but only use it; _if_ I should find the time, I'll write a more
  2402.     suitable TSR-unit on my own)
  2403.  - Especially if you save a screen as a PIC file, it will take quite a long
  2404.    time until GRAB finishes its operation - be patient!
  2405.  
  2406. See also   : MAKES, Palette
  2407.  
  2408.  
  2409. GraphTextBackground, GraphTextColor, GraphTextOrientation - variables
  2410. ─────────────────────────────────────────────────────────────────────
  2411.  
  2412. Function   : Determine how the OutTextXY()-procedures work
  2413.  
  2414. Declaration: TYPE  FontOrient=(horizontal,vertical);
  2415.              CONST GraphTextOrientation:FontOrient=horizontal;
  2416.                    GraphTextColor:BYTE=white;
  2417.                    GraphTextBackground:BYTE=white;
  2418.  
  2419. Description: Whenever text is to be written to the graphic screen, AniVGA
  2420.              consults some global variables. GraphTextColor is simply the color
  2421.              in which the text should be drawn, GraphTextBackground specifies
  2422.              the color for the pixels in between the letters with one special
  2423.              value: if GraphTextBackground=GraphTextcolor, then only the pixels
  2424.              belonging to the letters will be drawn with all others remaining
  2425.              unchanged.
  2426.              Of course, if you are using a colored font, then the font itself
  2427.              determines its colors. The only exception of that rule is color
  2428.              0, which is treated as in the monochrome case: if
  2429.              GraphTextBackground=GraphTextcolor, then only the pixels
  2430.              belonging to the letters will be drawn with all others remaining
  2431.              unchanged.
  2432.              Finally, GraphTextOrientation tells AniVGA in which direction the
  2433.              text should be written with two values being possible: HORIZONTAL
  2434.              (default) for left-to-right text and VERTICAL for top-to-bottom
  2435.              style text.
  2436.  
  2437. Note       : Default (monochrome) color for the text is "white/white" =
  2438.              "white and don't change pixel values between letters".
  2439.  
  2440. See also   : OutTextXY, BackgroundOutTextXY
  2441.  
  2442.  
  2443. HitDetect - function
  2444. ────────────────────
  2445.  
  2446. Function   : Checks whether two sprites collide or not
  2447.  
  2448. Declaration: FUNCTION Hitdetect(s1,s2:INTEGER):BOOLEAN; FAR;
  2449.  
  2450. Description: Call this routine with the sprite numbers of the two sprites to be
  2451.              checked for collision; the function will return TRUE/FALSE when
  2452.              the sprites collide/do not collide, respectively.
  2453.  
  2454. Note (!)   : - Collision detection is independent of whether the sprites are
  2455.                visible or offscreen: AniVGA uses the corrdinates of the two
  2456.                sprites given (in SpriteX/Y) and internal data to check.
  2457.              - For this it is possible to check for collisions _before_ drawing
  2458.                an image (with Animate) and thus make necessary sprite updates
  2459.                at once!
  2460.              - Inactive sprites cannot collide:
  2461.                (SpriteN[s1] or SpriteN[s2]=0) -> FALSE
  2462.              - A sprite can't collide with itself: (s1=s2 -> FALSE)
  2463.  
  2464. See also   : Collision-detection
  2465.  
  2466.  
  2467. InitGraph - procedure
  2468. ─────────────────────
  2469.  
  2470. Function   : Initialises the VGA card for the use with AniVGA
  2471.  
  2472. Declaration: PROCEDURE InitGraph; FAR;
  2473.  
  2474. Description: AniVGA uses a special graphic mode, which supports 4 graphic pages
  2475.              in the resoultion 320x200 pixels and 256 colors. Because this mode
  2476.              is not known by the VGA's BIOS, AniVGA has to reprogram the VGA.
  2477.              You should use this command only once to switch into graphic mode.
  2478.  
  2479. Note       : InitGraph automatically switches to the invisible graphic page
  2480.              1-PAGE.
  2481.  
  2482. See also   : Screen, CloseRoutines
  2483.  
  2484.  
  2485. InitRoutines - procedure
  2486. ────────────────────────
  2487.  
  2488. Function   : Resets all necessary internal variables of AniVGA to initial values
  2489.  
  2490. Declaration: PROCEDURE InitRoutines FAR;
  2491.  
  2492. Description: At program start, some variables have to be set and a few system
  2493.              checks are necessary.
  2494.              Among these are:
  2495.              - SpriteN[], SpriteAd[], SpriteSize[], SpritePTR[] and BackTile[]
  2496.                become cleared (=set to 0 or NIL, respectively)
  2497.              - Page (the actual drwaing page) is set to 0
  2498.              - PageAdr is set to the segment address of the drawing page PAGE
  2499.              - BackgroundMode is set to STATIC, i.e.: non-scrollable background
  2500.              - BackGndAdr is set to the segment address of the background image
  2501.              - StartVirtualX/Y are set to (0,0), making the normal screen coor-
  2502.                dinates identical to the virtual screen coordinates
  2503.              - the old graphic/text mode which was active at program start is
  2504.                stored for restoring it at the program end
  2505.              - the system is checked if a VGA card is present and the global
  2506.                variable ERROR is set accordingly
  2507.              - CycleTime is set to 0, which says that there should be no time-
  2508.                control mechanism for the animation rate
  2509.              - if the machine is not at least an AT, the time mechanism is
  2510.                switched off completely
  2511.              - COLOR is set to 15 (= white)
  2512.              - the internal monochrome 6x6 font is activated
  2513.              - the FONT* variables are set accordingly
  2514.  
  2515.              The first thing you should do in your programs is to look at the
  2516.              ERROR variable: if it was set to something different from Err_None
  2517.              (by the implicit, automatical call of InitRoutines) then your pro-
  2518.              gram should not proceed further.
  2519.  
  2520. Note       : - This routine is called automatically at the very beginning of
  2521.                every program which uses AniVGA. For that, there is normally no
  2522.                need to call this routine explicitly.
  2523.              - Possible ERROR-values returned are: Err_None and Err_NoVGA
  2524.              - Note that this is the _only_ routine that definitely sets the
  2525.                variable ERROR, either to Err_None or Err_NoVGA. Because it is
  2526.                called at the beginning of every program, it is thus assured
  2527.                that your application always has a defined value for ERROR!
  2528.  
  2529. See also   : ERROR
  2530.  
  2531.  
  2532. IntroScroll - procedure
  2533. ────────────────────────
  2534.  
  2535. Function   : Does a hardware scroll on the video RAM
  2536.  
  2537. Declaration: PROCEDURE IntroScroll(n,wait:WORD) FAR;
  2538.  
  2539. Description: A feature often asked is a big, smooth scrolling intro screen.
  2540.              This can be done with IntroScroll(): you load up to 4 graphic
  2541.              pics into the 4 graphic pages 0..3 and then issue IntroScroll.
  2542.              The scroll will *always* start at graphic page 0 and last "n"
  2543.              rows. After each row being scrolled, the system will pause for
  2544.              "wait" milliseconds before the next line will be scrolled.
  2545.              This routine is only for an intro, you can't use sprites in
  2546.              parallel and must issue a "Screen(1-page)" command afterwards!!!
  2547.              A small example:
  2548.  
  2549.                 USES AniVGA;
  2550.                 BEGIN
  2551.                  InitGraph; {program VGA card into graphic mode}
  2552.  
  2553.                  {--- Start Of Intro ---}
  2554.                  Screen(0); {show page 0; not necessary, but nicer :-) }
  2555.  
  2556.                  {Fill all 4 pages with data; of course you could also }
  2557.                  {restrict yourself to pages 0..2 or 0..1:}
  2558.                  LoadPage('3rd.PIC',1); {load temporarily to page 1}
  2559.                  {move picture to VRAM area of former background page:}
  2560.                  CopyVRAMtoVRAM(Ptr($A000,1*PAGESIZE),
  2561.                                 Ptr($A000,2*PAGESIZE),
  2562.                                 PAGESIZE);
  2563.                  LoadPage('1st.PIC',0);
  2564.                  LoadPage('2nd.PIC',1);
  2565.                  LoadPage('4rd.PIC',3);
  2566.  
  2567.                  IntroScroll(3*200,20); {scroll up 3 pages, wait 20ms}
  2568.                  {as scrolling starts at page 0, you will end up at page 3}
  2569.  
  2570.                  READLN;         {wait for a CR by the user}
  2571.                  Screen(1-page); {restore correct mode, this is a must!!!}
  2572.                  {--- End Of Intro ---}
  2573.  
  2574.                  {now do your animations as usual: sprites, backgrounds, etc.}
  2575.                  {...}
  2576.                  CloseRoutines;
  2577.                 END.
  2578.  
  2579.              Note the special treatment of the picture "3rd.pic": a simple
  2580.              "LoadPage('3rd.PIC',2)" wouldn't work, as it would load the
  2581.              picture into the background page --but this has been moved to
  2582.              normal RAM (or EMS) in V1.2. However, for a hardware scroll, the
  2583.              data *must* be in consecutive order in the VRAM area! So we load
  2584.              the pic into some other VRAM page and move it to the right place.
  2585.              (If you don't understand: don't mind, just behave as in the
  2586.               example above!)
  2587.              
  2588. Note       : - This routine is thought for *intros*! Remember that graphic
  2589.                pages 2 and 3 (=BACKGNDPAGE and SCROLLPAGE) are used by AniVGA
  2590.                for other purposes, so if you use them for your intro, don't
  2591.                forget to fill them later with the proper contents for your
  2592.                animations! (In version V1.2, BACKGNDPAGE has been moved to
  2593.                RAM, so its former VRAM address range has been freed).
  2594.              - You have to issue a "Screen(1-page)" command at the end of your
  2595.                intro to reset the VGA card properly!
  2596.              - It's merely for this routine that AniVGA's routines allow you
  2597.                to treat pages 2 and 3 as "normal" graphic pages.
  2598.              - This routine is "the hacker's toolkit". You are discouraged
  2599.                to use it; maybe it won't be supported in future versions or
  2600.                its interface will change.
  2601.  
  2602. See also   : CopyVRAMtoVRAM, FadeIn
  2603.  
  2604.  
  2605. Library files - information
  2606. ───────────────────────────
  2607.  
  2608. The term "library" is used in two meanings throughout the manual:
  2609. - in specifying a sprite library file (*.LIB)
  2610. - in specifying a collection of data sets (of any kind, although that's more
  2611.   theoretical for our considerations here) in a compressed file
  2612. I'll reference you to "Sprite library" for the first point and to "BFFFFFFF"
  2613. for the second one; this paragraph is just to remind you, that there are these
  2614. two different meanings.
  2615. However, you shouldn't get the chance to get confused: a sprite library is
  2616. just a collection of data sets (namely: sprites), too. So these two terms can
  2617. be seen as identical for your purposes, as long as you remember what is said
  2618. at the "BFFFFFFF" description: never compress a (sprite) library, which has
  2619. already one or more compressed sprites in it.
  2620. If you live up to that rule (or doesn't use compression of *.LIB files at
  2621. all), then just forget about this section!
  2622.  
  2623.  
  2624. Line - procedure
  2625. ────────────────
  2626.  
  2627. Function   : Draw a line between the two points specified
  2628.  
  2629. Declaration: PROCEDURE Line(x1,y1,x2,y2:INTEGER; pa:WORD); FAR;
  2630.  
  2631. Description: Calling this routine will draw a line between the two points
  2632.              (x1,y1) and (x2,y2) on graphic page "pa" and in the color COLOR.
  2633.              The routine uses virtual coordinates and clips the line down to
  2634.              its visible part.
  2635.              "pa" must be one of the values 0, 1, BACKGNDPAGE (=2) or
  2636.              SCROLLPAGE (=3).
  2637.  
  2638. Note       : - As with all point-setting procedures of AniVGA, you have to re-
  2639.                member AniVGA's working scheme: the first thing AniVGA does when
  2640.                Animate becomes executed is to copy the background image to the
  2641.                actual drawing page PAGE, erasing everything on that image.
  2642.                For this reason, a line drawn on the visible page 1-PAGE will be
  2643.                visible exactly one animation cycle.
  2644.              - Possible ERROR-values returned are: Err_InvalidPageNumber
  2645.  
  2646. See also   : PutPixel, BackGroundLine, coordinates
  2647.  
  2648.  
  2649. LoadBackgroundPage - procedure
  2650. ──────────────────────────────
  2651.  
  2652. Function   : Loads a background image from disk
  2653.  
  2654. Declaration: PROCEDURE LoadBackgroundpage(name:String); FAR;
  2655.  
  2656. Description: This routine loads a bitmap image stored in file "name" into the
  2657.              graphic page used for the background image (BACKGNDPAGE).
  2658.  
  2659. Note (!)   : - This routine must be called *after* the graphic mode has been
  2660.                initialized (with InitGraph())!
  2661.              - You can create such images either with the WritePage()- and
  2662.                WriteBackgroundPage()-routines of AniVGA or the GRAB-Utility.
  2663.              - Calling this routine is equivalent to use the routine LoadPage()
  2664.                with BACKGNDPAGE as second argument.
  2665.              - Possible ERROR-values returned are: Err_FileIO and Err_NoPicture
  2666.  
  2667. See also   : Background, LoadPage, FillBackground, GetBackgroundFromPage,
  2668.              InitGraph, FindFile
  2669.  
  2670.  
  2671. LoadFont - procedure
  2672. ────────────────────
  2673.  
  2674. Function   : Loads a font file from disk
  2675.  
  2676. Declaration: PROCEDURE LoadFont(name:String); FAR;
  2677.  
  2678. Description: With this function, you load a font from disk into memory and
  2679.              make it the actual font. "name" is the MSDos-name of the font
  2680.              (*.FNT) file or the empty string '' to reset the font used to
  2681.              the internal monochrome 6x6 font.
  2682.  
  2683. Note       : - Only one font may be in use at one time; loading a new one
  2684.                cancels the old one
  2685.              - The variables FontHeight, FontWidth, FontType, FontProportion,
  2686.                FontWidthTable[] and CurrentFont, which are linked to a font,
  2687.                are adjusted automatically
  2688.              - Possible ERROR-values are: Err_FileIO, Err_NotEnoughMemory and
  2689.                Err_NoFont
  2690.  
  2691. See also   : FontHeight, FontWidth, FontType, Font files, FindFile
  2692.  
  2693.  
  2694. LoadMAX - constant
  2695. ──────────────────
  2696.  
  2697. Function   : Specifies the maximum number of different sprites
  2698.  
  2699. Declaration: CONST LoadMAX=1000;
  2700.  
  2701. Description: For each physical sprite, AniVGA uses an internal pointer to its
  2702.              data. There are LoadMAX pointers, thus there may be up to LoadMAX
  2703.              different spriteLOADnumbers (= different sprites).
  2704.  
  2705. Note       : Don't mix this constant up with NMAX!
  2706.  
  2707. See also   : NMAX, SPRITE, SpriteLOADnumbers, Spritenumbers
  2708.  
  2709.  
  2710. LoadPage - procedure
  2711. ────────────────────
  2712.  
  2713. Function   : Loads a graphic page from disk
  2714.  
  2715. Declaration: PROCEDURE LoadPage(name:STRING; pa:WORD); FAR;
  2716.  
  2717. Description: "name" is the MSDOS-path to the graphic image to load, pa the
  2718.              destination page (0, 1, BACKGNDPAGE (=2) or SCROLLPAGE (=3)).
  2719.  
  2720. Note       : - The graphic mode must have been initialized (vià InitGraph)
  2721.                already!
  2722.              - You can generate disk files of graphic pages with the help of
  2723.                the WritePage()-routine or with the GRAB-utility program.
  2724.              - Don't use this routine to load an image into the SCROLLPAGE,
  2725.                i.e.: in background mode SCROLLING!
  2726.              - Possible ERROR-values returned are: Err_InvalidPageNumber,
  2727.                Err_FileIO and Err_NoPicture
  2728.  
  2729. See also   : GRAB, WritePage, background, InitGraph, FindFile
  2730.  
  2731.  
  2732. LoadPalette - function
  2733. ──────────────────────
  2734.  
  2735. Function   : Loads a palette into memory
  2736.  
  2737. Declaration: FUNCTION LoadPalette(name:String; number:BYTE;
  2738.                                   VAR pal:Palette):WORD;
  2739. Description: "name" is the MSDOS-name of the palette file (*.PAL) to load,
  2740.              "number" is the index of the first loaded color in the desti-
  2741.              nation array "pal". For example,
  2742.               LoadPalette('C:\AniVGA\TEST.PAL',0,my_pal)
  2743.              would load the named palette file into my_pal and the first color
  2744.              of this file would be stored in my_pal[0], the second in
  2745.              my_pal[1] and so on. (This call - "number" set to 0 - will be
  2746.              the form you'll need in 99% of all cases!)
  2747.              The routine will read in the complete file and return the number
  2748.              of colors read as result.
  2749.              All other colors in "pal" before "number" or after the end of the
  2750.              specified pal-file will stay untouched!
  2751.  
  2752. Note       : - As the routine reads in the complete file, you must take care
  2753.                not to write beyond the end of "pal"! Especially, if you load
  2754.                a complete 256-color palette (size: 3*256=768 bytes), you must
  2755.                start at color index 0 (that is: number=0) or you'll get an
  2756.                "Err_PaletteWontFit"-Error! Most often however, you will use
  2757.                this routine as in the example above.
  2758.              - Other possible errors are: Err_FileIO and Err_NoPalette
  2759.              - You can call this routine only after having called InitGraph()!
  2760.              - You can directly load into ActualColors, that is the sequence:
  2761.                 Dummy:=LoadPalette(pal_name,0,ActualColors);
  2762.                 SetPalette(ActualColors);
  2763.                is valid!
  2764.  
  2765. See also   : palettes, SetPalette, GetPalette, FindFile
  2766.  
  2767.  
  2768. LoadSprite - function
  2769. ─────────────────────
  2770.  
  2771. Function   : Loads one (or more) sprites into memory
  2772.  
  2773. Declaration: FUNCTION LoadSprite(name:String; number:WORD):WORD; FAR;
  2774.  
  2775. Description: "name" is the MSDOS-name of the sprite file to load, which can be
  2776.              either a single sprite file (*.COD) or a complete sprite library
  2777.              (*.LIB): the function will detect automatically, which format is
  2778.              used while loading the data.
  2779.              "number" is the spriteLOADnumber, the first loaded sprite will be
  2780.              assigned to. If the file contains more than one sprite, they will
  2781.              get consecutive LOADnumbers.
  2782.              The value returned by the function is the numbers of sprites read
  2783.              in (i.e.: 0 means "no sprite read", so you should check ERROR in
  2784.              that case).
  2785.  
  2786. Note       : - Unlike LoadTile(), LoadSprite() loads data into conventional
  2787.                memory. For that, you don't have to be in graphic mode to load
  2788.                data from disk!
  2789.              - If you load a sprite at a LOADnumber already used, the old
  2790.                sprite will become erased automatically by a call to
  2791.                FreeSpriteMem()
  2792.              - Possible ERROR-values returned are: Err_FileIO, Err_NoSprite,
  2793.                Err_NotEnoughMemory and Err_InvalidSpriteNumber
  2794.  
  2795. See also   : FreeSpriteMem, sprite format, MAKES, FindFile
  2796.  
  2797.  
  2798. LoadTile - function
  2799. ───────────────────
  2800.  
  2801. Function   : Loads one or more tiles from disk
  2802.  
  2803. Declaration: FUNCTION LoadTile(name:STRING; number:BYTE):WORD; FAR;
  2804.  
  2805. Description: This routine loads the background tile file "name" into the
  2806.              graphic memory area reserved for tiles (the SCROLLPAGE).
  2807.              The starting number for the first tile of the file is "number";
  2808.              if there is more than one tile in the named file, they will be
  2809.              loaded, too (with increasing numbers).
  2810.              The function returns the number of tiles read in.
  2811.  
  2812. Note (!)   : - This routine must be called *after* the graphic mode has been
  2813.                initialized (with InitGraph)!
  2814.                What the function actually does is reading in a sprite and con-
  2815.                verting it into an internal tile format: if the sprite read in
  2816.                doesn't have the proper size of a tile (16x16 pixels), you nor-
  2817.                mally will get an appropriate error (Err_NoTile), with one (use-
  2818.                ful) exception: if the sprite can be "cut" into tiles (that is,
  2819.                its width and height are multiples of 16 pixels each), then
  2820.                LoadTile() will do so with the following numbering scheme: from
  2821.                left to right and from top to bottom.
  2822.                For example, a sprite with (width,height)=(3*16,2*16) points
  2823.                would be numbered as: (assuming that "number" = 0)
  2824.                ┌────────┬────────┬────────┐
  2825.                │        │        │        │
  2826.                │   0    │   1    │   2    │
  2827.                │        │        │        │
  2828.                ├────────┼────────┼────────┤
  2829.                │        │        │        │
  2830.                │   3    │   4    │   5    │
  2831.                │        │        │        │
  2832.                └────────┴────────┴────────┘
  2833.                Besides, LOADTILE can load a sprite library, too (they will be
  2834.                loaded in the sequence in which they appear in the library).
  2835.              - Possible ERROR-values returned are: Err_NotEnoughMemory,
  2836.                Err_FileIO, Err_NoTile and Err_InvalidTileNumber
  2837.  
  2838. See also   : Background, LOADSPRITE, TILE, FindFile
  2839.  
  2840.  
  2841. MAKES - utility
  2842. ───────────────
  2843.  
  2844. The design of sprites, background pictures and tiles is much to tedious to be
  2845. carried out manually. For this reason, there are two utility programs to
  2846. simplify that task. The first one is a resident program named "GRAB" to
  2847. capture graphics from other applications and convert them into sprites, the
  2848. second is MAKES, a spritemaker program.
  2849. To use it, you must have a mouse installed and a Super-VGA card.
  2850.  
  2851. -> MAKES uses a "tweaked" 640x400x256 graphic mode, only available at Super-
  2852.    VGA-cards! If you don't have one (or one which chip-set isn't supported by
  2853.    the supplied BGI-driver), you won't be able to run MAKES!
  2854.    Let me cite from Jordan Hargrave's docs:
  2855.  
  2856.    >Card types supported: (SuperVGA drivers)
  2857.    >Ahead, ATI, Chips & Tech, Everex, Genoa, Paradise, Oak, Trident (both 8800
  2858.    >and 8900), Tseng (both 3000 and 4000 chipsets) and Video7.
  2859.    >These drivers will also work on video cards with VESA capability.
  2860.    >
  2861.    >I have not tested these drivers on all these card types, so I can not
  2862.    >guarantee perfect operation with your card.  I have tested them extensively
  2863.    >on Trident, Tseng and ATI cards, and have had no problems. (Trident 8800
  2864.    >cards occasionally have problems, especially older models)
  2865.    
  2866.    If you can't run MAKES, then please drop me a note specifying which brand of
  2867.    VGA card you have and which chip-set it uses!
  2868.  
  2869. There are normally no parameters or such things, just start it!
  2870. (However, if you _do_ have a SVGA and MAKES does not show its graphic screen
  2871.  properly, then use the syntax "MAKES /480" to invoke the program in
  2872.  640x480x256 graphic mode instead)
  2873.  
  2874. The screen is divided in several areas:
  2875.  - the so-called "work area" in the upper left region, in which you paint your
  2876.    sprite
  2877.  - the palette area to the right of it, where you choose colors for painting
  2878.    or define new colors
  2879.  - the info bar right beneath the work area, which informs you about the
  2880.    cursor position and some other actually set data
  2881.  - the icon field, supplying 18 different functions: 8 "tools" and 10 pure
  2882.    functions
  2883.  - 10 function boxes at the very screen bottom, which can also be accessed by
  2884.    pressing the appropriate function key (ever seen the Norton Commander?)
  2885.  
  2886. (Note that a lot of the icons/function boxes have two functions, where the
  2887.  second one can be reached by holding down the shift-key while pressing/
  2888.  clicking at the icon - this will be described later on, but you can always
  2889.  press F1 in MAKES for a short summary.)
  2890.  
  2891.  
  2892. Now let's take a small tout through MAKES!
  2893.  
  2894. -> I propose that you print out this part of the documentation and then start
  2895.    MAKES.EXE for the following description!!!
  2896.  
  2897. Huh - where to begin? Okay, look at the work area's boundary: it has small
  2898. marks on it, indicating 8 pixel intervals. Move the mouse cursor somewhere into
  2899. the workarea: right beneath the work area, your PC will display the mouse
  2900. cursor's position and what color is currently set at that point. Now move around
  2901. and convince yourself about the marks' values. Press the left mouse button a
  2902. few times: each time, a white pixel will be drawn at the cursor position,
  2903. because "pixel" is the selected tool and "white" the actually set drawing color.
  2904. Nothing whopping, eh? - Now press "+" a few times: wow! You zoom into the work
  2905. area as much as you wish (well, I limited it to a factor 30, but if _that_ is
  2906. not enough you should consider selling your PC for a seeing-eye dog, anyway!).
  2907. Use "-" to zoom out, down to value 1: for easier pointing, the cursor will
  2908. change to a small crosshair pointer when zooming is at factor 1.
  2909. -> Note that as the screen you look at has resolution 640x400, while AniVGA's
  2910.    has 320x200, zoom=2 (the default value) will give you normal 1:1 aspect
  2911.    ratio!
  2912. You don't like monochrome pictures? Ok, then click (with the left mouse button)
  2913. at another color in the palette area: this changes the drawing color to the
  2914. color you clicked at.
  2915. Repeat choosing a color, but this time press the _right_ mouse button: a menu
  2916. will pop up and let you change the RGB-values of that color; this way, you may
  2917. alter the palette for your sprites!
  2918. -> Note that RGB-values reach from 0 to 63. If you want to copy another color's
  2919.    values, then just click at this color; e.g. if you want to have color 222
  2920.    hold the same color as 111 (for example as a template), then click with the
  2921.    _right_ button at color 222 and then with the _left_ button at color 111
  2922. Now choose another drawing tool, let's say lines: click at this icon and move
  2923. back into the work area. Choose a starting point and click at it (release the
  2924. mouse button!): now you started a line: move around the mouse to route your
  2925. line; if you are content with it, then press the left button again. If you
  2926. decide to cancel the line drawing instead, then press the right button instead.
  2927. -> This "philosophy" will be used for all tools: press the left button to
  2928.    start/advance/complete an action, press the right button any time to cancel
  2929.    what you are doing - so get used to it!
  2930. Now repeat the process of drawing a line, but hold down "shift" while you are
  2931. clicking at the starting point: this tells the object "to be aligned" which
  2932. in the context of lines means that you are drawing a horizontal, vertical or
  2933. diagonal line! In the same way, you can align rectangles to become squares and
  2934. ellipses to circles. Try it! Choose these icons and draw the according objects,
  2935. aligned and not aligned (if you choose the lower rectangle/ellipse icon, your
  2936. objects will be filled out with the actual drawing color).
  2937. -> You may select another color even if you are in midst of drawing an object;
  2938.    move out of the work area, click at the color you wish - as soon as you
  2939.    move back into the work area, your object will change!
  2940. Let's try the filling tool (the left, bottommost one): it will fill all points
  2941. it can reach from the pixel you clicked at having the same color, e.g. if you
  2942. click at a white pixel, it will color all white pixels neighboured to that
  2943. pixel and so on. Note that as long as you don't press the left button a second
  2944. time, this coloring doesn't rest, that is if you move around the mouse after
  2945. having clicked the first time, MAKES will restart its fill algorithm starting
  2946. at the new pixel your mouse points at! This behaviour is a bit confusing in
  2947. the beginning but comes in very handy when you get used to it.
  2948. -> If you really get stuck - especially on slow machines - then just press the
  2949.    right mouse button for two or three seconds to cancel the action and start
  2950.    over again.
  2951. The last tool to be mentioned is the copy tool (the icon with the scissors):
  2952. you can span a (dotted) rectangular area which you want to copy the same way
  2953. you would draw a rectangle, but after pressing the mouse button a second time,
  2954. a copy of this area will be visible at your cursor which you can place where-
  2955. ever you want to. (Note that color 0 inside this copy will be treated as trans-
  2956. parent, which makes it easier to overlay objects at the screen!)
  2957.  
  2958. These 8 icons (the 4 leftmost in the upper and lower row) make up the available
  2959. _tools_, the resting 10 icons are "function buttons", that is: their linked
  2960. action will take place at once (respectively: after asking you necessary para-
  2961. meters).
  2962. I'll first name them, starting in the upper row at the 5th icon, in clockwise
  2963. order:
  2964. a) change color
  2965. b) rotate work area left
  2966. c) rotate work area right
  2967. d) mirror work area horizontally
  2968. e) go/move to the upper-left
  2969. f) display boundaries
  2970. g) mirror work area vertically
  2971. h) rotate work area down
  2972. i) rotate work area up
  2973. j) blink color
  2974.  
  2975. a)
  2976.  You can replace pixels of a specific color by another color with this tool:
  2977.  the program will ask you for the colors, which you can select by either
  2978.  clicking in the palette area or by clicking at pixels in the work area itself.
  2979.  
  2980. b), c), h), i)
  2981.  Clicking at one of these buttons will move the contents of the work area in
  2982.  the according direction, but what "falls out" at one side of the work area
  2983.  will show up on the opposite side again. If you hold down "shift" while
  2984.  clicking, the image will rotate by one pixel, without shift, it will rotate
  2985.  by 1/4 of the actual screen width.
  2986.  
  2987. d), g)
  2988.  I guess these two mirror options should be quite clear; note that as
  2989.  they mirror a small image in the upper left corner to the "far away" right/
  2990.  bottom region of the work area, you'll often need a tool to "pull back" the
  2991.  graphic contents to the upper left corner: that is exactly the task of the
  2992.  e) icon: it will move the graphic contents to the top and left as much as
  2993.  possible.
  2994.  
  2995. e)
  2996.  As mentioned above, this tool will move the work area contents to the left
  2997.  (and top), until column 0 (row 0) holds a non-zero colored pixel.
  2998.  If you hold down "shift" while clicking at this icon, there is another
  2999.  functionality: then, MAKES scrolls back the visible part of the workarea
  3000.  back to the upper left region of the picture (0,0), that is: this is a short-
  3001.  cut for pressing the left- and up-arrow keys a few times (see below for more
  3002.  about this).
  3003.  
  3004. f)
  3005.  If you want to know/see the boundaries of your sprite, then click at this
  3006.  icon: the leftmost and rightmost (upmost & bottommost) pixel of each row
  3007.  (column) will blink and a popup window will inform you about the sprite's
  3008.  size numerically.
  3009.  If you hold down "shift" while clicking this icon, MAKES will also blink all
  3010.  transparent areas inside the sprite, which may be useful if you don't know
  3011.  whether you must use display mode Display_SHADOW <-> Display_SHADOWEXACT and
  3012.  Display_FAST <-> Display_NORMAL; in all other cases you can forget about this
  3013.  option.
  3014. -> Note that sprites are always stored as the smallest rectangle which
  3015.    surrounds them and starts at the upper left corner (0,0): if you don't have
  3016.    special reasons to do otherwise, your sprites should start in the upper left
  3017.    corner.
  3018.    If for example you realize a sprite consisting of one single point at
  3019.    coordinates (a,b), the smallest surrounding box with (0,0) as upper left
  3020.    corner would be
  3021.    (0,0)      (a,0)      of size (a+1)*(b+1) pixels (=bytes)!!!
  3022.      ┌──────────┐
  3023.      │          │
  3024.      │          │
  3025.      │          │
  3026.      └──────────▀   <─ this is your 1 point
  3027.    (0,b)      (a,b)
  3028.    (In addition to that, the right edge of this box will be rounded up so that
  3029.     the width of the sprite will be a multiple of 4)
  3030.    To determine what areas belong to your sprite and which don't, the program
  3031.    assumes color 0 to specify no-sprite-areas and all other colors to be part
  3032.    of your sprite (roughly spoken).
  3033.  
  3034. j)
  3035.  If for some reason you must know of all pixels of a specific color (e.g. to
  3036.  distinguish two very similiar colors), you can use this function: the program
  3037.  will ask you to select the color, what you can do by either clicking at a
  3038.  work area pixel with that color or at a color in the palette area.
  3039.  
  3040. Okay, now that we are through with the icons, let's have a look at the keys:
  3041. you already know that "+" and "-" zoom in and out the workarea. But if zoom>1
  3042. then only a part of the complete workarea (320x200 pixels) will be visible!
  3043. To work on the "offscreen" regions, you can scroll the work area by using the
  3044. cursor keys: pressing one of the arrow keys will scroll by 1/4 screen into the
  3045. corresponding direction; if you hold down "shift" while pressing an arrow key,
  3046. it will scroll by one pixel instead. The absolute coordinate value of the
  3047. upper left corner you are looking at will be displayed by the two "offset:"
  3048. messages, e.g. "offset X: 40" means that there are 40 columns (0..39) to the
  3049. left of the visible window of the work area, which you may scroll in by
  3050. pressing the left arrow key. (Consider the work area as a view-finder of an
  3051. imaginary camera which you may slide into each direction).
  3052. A short-cut to return to the work area's origin (0,0) is available, too: press
  3053. shift and click at the "go/move to upper left" icon.
  3054.  
  3055. The function keys do what they tell you:
  3056.  F1 = a short summary of the functionality not visible at first sight
  3057.  F2 = save the work area's contents to disk as a sprite file
  3058.  F3 = load a previously saved sprite into the work area; if you press "shift"
  3059.       while activating this icon (or Shift-F3), then the work area won't be
  3060.       erased before loading the sprite: this way, you may overlay several
  3061.       sprites on the screen
  3062.  F4 = save the actually set palette to disk. Note that if you are using the
  3063.       BIOS' default palette, the program won't store it to disk (as you don't
  3064.       need)
  3065.  F5 = load a previously saved palette. This function is especially necessary
  3066.       when you used GRAB to capture a sprite from an application using a
  3067.       different palette. (See below for more about palette handling)
  3068.  F6 = save the work area's contents to disk, this time as a background picture
  3069.  F7 = load a previously saved background picture; the same notes apply as said
  3070.       to loading sprites (F3)
  3071.  F8 = clear screen. This will erase the work area and let you start all over
  3072.       again. Note that it won't reset the palette to the BIOS' default! If you
  3073.       want that, you have to press Shift-F9, too!
  3074.  F9 = map the workarea colors onto another palette. This feature asks you for
  3075.       a palette, loads that and then uses a minimum square algorithm to exchange
  3076.       each's pixel color by the one from the specified palette which comes as
  3077.       close as possible to the original color. (See below for more about that)
  3078.       Shift-F9 works the same, but maps to the BIOS' default palette instead
  3079.       of asking you for a palette file.
  3080.  F10= quit the program
  3081.  
  3082.  
  3083. Note       :
  3084. o Palettes:
  3085.  Note that if you load/save a sprite or picture file, MAKES won't load/save
  3086.  the according palette automatically, you have to do that manually. This has
  3087.  been done intentionally, however: never forget that you may design a hundred
  3088.  sprites with a hundred different palettes, but when it all comes down to
  3089.  display these sprites simultaneously in your programs, only *one* palette may
  3090.  be active! For that reason, you must mix all those palettes to the one you are
  3091.  going to use. 
  3092.  Normally, that won't be that dramatic, as 240 free color shades (it is *very*
  3093.  wise not to change the first 16 EGA-compatible colors) seem enough to me, but
  3094.  perhaps you want to include a formerly designed sprite A, using palette B,
  3095.  into a new program where you use palette C! Before you start mixing a new
  3096.  palette D for this old and your new sprites together, you should try mapping
  3097.  old sprite A's colors to palette C: To accomplish that, load sprite A (using
  3098.  F3), then load its old palette B (using F5); now press "map palette to
  3099.  palette" (F9) and tell the program to map onto palette C: if the result looks
  3100.  good enough, then save sprite A (perhaps using a different name) and use
  3101.  palette C for all items in your program, else you have to find a compromise
  3102.  between palettes B and C (I'm actually working on a program which will auto-
  3103.  matize that job, but for now, you are on your own!).
  3104.  
  3105.  To state it clear: there is a conceptional difference between EXCHANGING a
  3106.  color (using the "change color" icon) and CHANGING a color itself (by altering
  3107.  the RGB values of one or multiple colors):
  3108.  - exchanging colors doesn't change the palette, it merely uses another color
  3109.    of that palette
  3110.  - changing palette colors doesn't change the pixels' color number, but the
  3111.    color's RGB value
  3112.  In other words: if you exchange colors, then you don't have to save the color
  3113.  palette again, as it didn't change, but the sprite, because its data changed.
  3114.  On the other hand, if you changed palette colors, then you'll have to save the
  3115.  palette, but not the sprite, as the pixel data didn't change.
  3116.  (If you didn't get that: just always save both and forget about it...)
  3117.  
  3118. o Mouse problems:
  3119.  I noticed that sometimes, the program hangs when initializing the mouse driver
  3120.  (when it calls "INT 33h" with AX=0), what you see in that the starting count-
  3121.  down doesn't get below 7. I don't have _any_ idea why this happens and hope
  3122.  it won't show up on other systems. Note that this is (at least what I noticed)
  3123.  a spurious error: cancel the program, restart it once more and it will work!
  3124.  Besides that, when quitting the program, MAKES sometimes reports a senseless
  3125.  runtime error - it is a spurious, not reproducable error I couldn't track
  3126.  down, either (perhaps TP doesn't like my TSR / QEMM installation, I dunno)!?
  3127.  
  3128. o SVGA-compatibility problems:
  3129.  The 640x400x256 mode seems to make problems on some SVGAs, especially ones
  3130.  with Paradise chipsets. Therefore, a command line switch "/480" has been
  3131.  added. If you use this switch, the program will start in 640x480x256 mode
  3132.  instead. I've been reported that this mode works on almost all cards; the
  3133.  only disadvantage is, that the aspect ratio differs from the 320:200 (resp.
  3134.  640:400) mode. (Tip: use your monitor's vertical adjustment controller to
  3135.  spread the image accordingly if this is a problem for you)
  3136.  
  3137. o Memory:
  3138.  You should have at least 256K free RAM if you start MAKES, or it won't work.
  3139.  
  3140. o Sprite size:
  3141.  If MAKES tells you that it can't save the workarea as a sprite, because it
  3142.  is "to big" - well, then you'll have to shrink your sprite! Sorry, but I
  3143.  wanted MAKES to handle CODs and PICs at the same time, but 320x200 pixels
  3144.  (the size of a picture) is to much for a COD, as the additional data stored
  3145.  along with the sprite would make it larger than 64K! (Cut off a few rows or
  3146.  columns until it works.)
  3147.  Note also that MAKES has to store sprites with widths being a multiple of 4!
  3148.  That is: it doesn't matter, whether the max. used x-coordinate is for example
  3149.  316, 317, 318 or 319, because for all those 4 widths (0..316=317 pixels,
  3150.  0..317=318, 0..318=319, 0..319=320), MAKES would have to store them with
  3151.  the "rounded up" width of 320 pixels!
  3152.  (In other words: although AniVGA itself can handle sprites up to 32000 pixels
  3153.   in each axis and 64K max. size, MAKES restricts you to sprites of x-size at
  3154.   most 320 pixels and y-sizes of at most 200 pixels)
  3155.  
  3156. o COD <-> PIC:
  3157.  Yes, you read right: MAKES doesn't care whether you are working on a sprite
  3158.  or a picture graphic: just paint it and store it into the format you want
  3159.  (subject to what I said above concerning the 64K limit)! Oh yes, that way
  3160.  you may convert a sprite into a background picture (and vice versa) if you
  3161.  have reason to do so!
  3162.  
  3163. o Tips:
  3164.  
  3165.  The best way to design a sprite is to start in midst of a cleared work area.
  3166.  If you need more room, rotate your sprite in the appropriate direction.
  3167.  If you think you're done, use the rotate boxes again (or the "move to upper-
  3168.  left" icon) to align your sprite with the upper left corner. Then click on
  3169.  the "display boundaries" box to compare the sprite's size with what you
  3170.  expected. To wide (high)? Then there is a pixel with color <> 0 to the right
  3171.  (beneath) your sprite! Look at the max. column (row) MAKES told you and kill
  3172.  that pixel! (To see it more clearly, just hold down "shift" while clicking
  3173.  at the "display boundaries" icon).
  3174.  
  3175.  If you are unsure whether you can use display mode Display_FAST or need
  3176.  Display_NORMAL (same applies for Display_SHADOWEXACT and Display_SHADOW),
  3177.  then hold down "shift", click at the "display boundaries" icon and look at
  3178.  the picture: if the blinking parts "spread" out of the parts you think your
  3179.  sprite should be made of, then you should use Display_NORMAL
  3180.  (Display_SHADOWEXACT, respectively), if all the blinking areas are inside your
  3181.  sprite, you can (and should) use Display_FAST (Display_SHADOW).
  3182.  
  3183. See also   : sprite format, GRAB, Display modes
  3184.  
  3185.  
  3186. MakeTileArea - procedure
  3187. ────────────────────────
  3188.  
  3189. Function   : Simplifies tiling of the background area
  3190.  
  3191. Declaration: PROCEDURE MakeTileArea(FirstTile:BYTE;
  3192.                                     TileWidth,TileHeight:INTEGER); FAR;
  3193.  
  3194. Description: When using background mode SCROLLING, you have to define which
  3195.              tile should be "pasted" where in the coordinate space.
  3196.              You can do so manually for complete control, but most often,
  3197.              you just want to repeat a rectangular pattern throughout the
  3198.              complete scroll range which you did define before.
  3199.              This is exactly what MakeTileArea() does for you: you tell it
  3200.              in "FirstTile" the index of the first tile to use and the width
  3201.              and height of your pattern in tiles in "TileWidth" and
  3202.              "TileHeight" and it will paint this pattern throughout the
  3203.              defined background scroll range.
  3204.              For example, let's assume that you have a pattern 3 tiles wide
  3205.              and two 2 tiles high. The starting tile has index 7:
  3206.               ┌──┬──┬──┐
  3207.               │ 7│ 8│ 9│
  3208.               ├──┼──┼──┤
  3209.               │10│11│12│
  3210.               └──┴──┴──┘
  3211.              To set up the background area to a repetive pattern structure
  3212.              like that...
  3213.               ┌──┬──┬──┬──┬──┬──┬──┬
  3214.               │ 7│ 8│ 9│ 7│ 8│ 9│ 7│...
  3215.               ├──┼──┼──┼──┼──┼──┼──┼
  3216.               │10│11│12│10│11│12│10│...
  3217.               ├──┼──┼──┼──┼──┼──┼──┼
  3218.               │ 7│ 8│ 9│ 7│ 8│ 9│ 7│...
  3219.               ├──┼──┼──┼──┼──┼──┼──┼
  3220.               │10│11│12│10│11│12│10│...
  3221.               ├──┼──┼──┼──┼──┼──┼──┼
  3222.                 .  .  .  .  .  .  .
  3223.                 .  .  .  .  .  .  .
  3224.  
  3225.               ...all you have to do is a call MakeTileArea(7,3,2)!
  3226.  
  3227. Note (!)   : - Of course, usage of this routine requires that you are using
  3228.                background mode SCROLLING _and_ that you had issued a call to
  3229.                SetScrollRange() before!
  3230.  
  3231. See also   : Background, SetScrollRange
  3232.  
  3233.  
  3234. MaxTiles - constant
  3235. ───────────────────
  3236.  
  3237. Function   : Holds the maximum number of tiles to build the background image
  3238.  
  3239. Declaration: CONST MaxTiles=10000;
  3240.  
  3241. Description: In background mode SCROLLING, you may use up to MaxTiles tiles
  3242.              to build your graphic image.
  3243.  
  3244. Note       : -
  3245.  
  3246. See also   : Background
  3247.  
  3248.  
  3249. NextSprite - variables
  3250. ──────────────────────
  3251.  
  3252. Function   : Holds the "successors" of sprites for sprite cycles
  3253.  
  3254. Declaration: VAR NextSprite: ARRAY [0..LoadMAX] OF WORD
  3255.  
  3256. Description: To realize a sprite cycle, you must tell AniVGA which sprites
  3257.              should be drawn one after another. It is this information
  3258.              NextSprite holds! For example, let us assume that you wanted to
  3259.              make the sprite(loadnumber)s 43, 177 and 111 a sprite cycle, i.e.:
  3260.              whenever you set a sprite (to be precise: a SpriteN[]-entry) to
  3261.              one of these three numbers, AniVGA should cycle between the three
  3262.              sprite-images in the sequence 43->177->111->43->177->111->...
  3263.              You would then set NextSprite[43]:=177; NextSprite[177]:=111 and
  3264.              NextSprite[111]:=43  (don't forget this final value!) to do so.
  3265.  
  3266. Note (!)   : - Most often, you will have the situation that some sprite(load)-
  3267.                numbers with consecutive numbers should make up a cycle. In that
  3268.                case it is more convenient to use the SetSpriteCycle()-procedure
  3269.                to do the job for you
  3270.              - Again, note that the routine deals with spriteLOADnumbers! That
  3271.                is intentionally, because a sprite cycle is related to the
  3272.                _physical_ existent sprite data, or simply spoken: if you make
  3273.                5 pictures to form a flickering torch and you are going to use
  3274.                10 torches in your animation then each of them should loop
  3275.                through this 5-picture-cycle, shouldn't it?
  3276.              - NextSprite[] is initially set "to point to itself", that is:
  3277.                NextSprite[i]=i for all possible i's. If you had to break off
  3278.                a sprite cycle (though I can't think what this should be good
  3279.                for...), you must restore this data, e.g.: if you wanted to
  3280.                break the sprite cycle above, you would have to set
  3281.                NextSprite[43]:=43; NextSprite[177]:=177; NextSprite[111]:=43;
  3282.              - As this is a global variable, AniVGA can't check whether your
  3283.                settings make sense or not; thus, it remains your responsibi-
  3284.                lity to use proper values!
  3285.  
  3286. See also   :   SetSpriteCycle, Sprite cycles
  3287.  
  3288.  
  3289. NMAX - constant
  3290. ───────────────
  3291.  
  3292. Function   : Determines the maximum of sprites to be active at the same time
  3293.              (minus 1)
  3294.  
  3295. Declaration: CONST NMAX=499
  3296.  
  3297. Description: This constant sets the size of the internal tables - and thus the
  3298.              valid sprite numbers: the indices of the tables SpriteX, SpriteY
  3299.              and SpriteN must lie in the range 0..NMAX.
  3300.              To state it otherwise, there may be up to NMAX+1 sprites creeping
  3301.              around your screen at the same time...
  3302.  
  3303. Note       : Don't confound that constant with LoadMAX
  3304.  
  3305. See also   : LoadMAX
  3306.  
  3307.  
  3308. OutTextLength - function
  3309. ────────────────────────
  3310.  
  3311. Function   : Computes the length of a string in pixels
  3312.  
  3313. Declaration: FUNCTION OutTextLength(s:STRING):WORD; FAR;
  3314.  
  3315. Description: Fonts in AniVGA may be proportional spaced, so it could be hard
  3316.              to compute the length of a string. This function does exactly
  3317.              that: it computes the length of string "s" and takes care of
  3318.              proportional font widths and the like.
  3319.  
  3320. Note       : - Unlike CRT.Length, this function returns the length in _pixels_
  3321.  
  3322. See also   : FontWidth, FontWidthTable
  3323.  
  3324.  
  3325. OutTextXY - procedure
  3326. ─────────────────────
  3327.  
  3328. Function   : Writes a textstring to the graphic screen
  3329.  
  3330. Declaration: PROCEDURE OutTextXY(x,y:INTEGER; pa:WORD; s:STRING); FAR;
  3331.  
  3332. Description: Besides a built-in monochrome font, each character consisting of
  3333.              6x6 pixels (small, but very ugly...), AniVGA has the capability
  3334.              to load font files from disk, either monochrome or colored fonts.
  3335.              To write the string "s" to the graphic screen, you must specify
  3336.              the upper left starting corner of the text in (x,y):
  3337.                  (x,y) -> ▄──────────┐ , where (x,y) are virtual coordinates!
  3338.                           │          │
  3339.                           │          │
  3340.                           │          │
  3341.                           └──────────┘
  3342.              The text will be drawn in color GRAPHTEXTCOLOR and with the orien-
  3343.              tation GRAPHTEXTORIENTATION ("VERTICAL" or "HORIZONTAL").
  3344.              A third global variable, GRAPHTEXTBACKGROUND, specifies the color
  3345.              which will be used for the background area "beneath" the text
  3346.              letters with monochrome fonts (of course, colored fonts determine
  3347.              their pixel's colors themselves);
  3348.              if GRAPHTEXTCOLOR=GRAPHTEXTBACKGROUND then the text will be drawn
  3349.              like TurboPascal's routine does: only the pixels belonging to the
  3350.              letters will be drawn, all others remain unchanged.
  3351.              This also is the only exception valid for colored fonts, too:
  3352.              pixels with color 0 are treated the same way: if GraphTextColor=
  3353.              GraphTextBackground, then they won't be drawn, else they will be
  3354.              drawn (with GraphTextBackground as color value).
  3355.              "pa" specifies the graphic page to be drawn on and must be one of
  3356.              the drawing pages (0 or 1) or the BACKGNDPAGE (=2) for background
  3357.              mode STATIC. (For special purposes, SCROLLPAGE (=3) will work,
  3358.              too)
  3359.  
  3360. Note       : - In 99% of all cases, you will output text to the visible
  3361.                screen, that is: "OutTextXY(someX,someY,1-PAGE,'foobar')"
  3362.              - Any text drawn to the working pages 0 or 1 will stay onscreen
  3363.                only for one animation cycle. If you want it permanent, then
  3364.                use BackGroundOutTextXY() in mode STATIC or replace any call
  3365.                to Animate() by the sequence
  3366.                 Animate();
  3367.                 OutTextXY(someX,someY,1-PAGE,my_text)
  3368.                which works in both modes STATIC & SCROLLING. (As always, if
  3369.                you are in mode SCROLLING and use absolute coordinates, the
  3370.                text will scroll with your graphic image, while if you use
  3371.                relative coordinates (relative to StartVirtualX|Y of course),
  3372.                then the text will stay at a definite physical monitor position.
  3373.                For example,
  3374.                 OutTextXY(StartVirtualX,StartVirtualY,1-PAGE,'Hi!')
  3375.                will tie the text to the upper left screen position)
  3376.              - Possible ERROR-values returned are: Err_InvalidPageNumber
  3377.  
  3378. See also   : GraphtextColor, GraphtextOrientation, GraphtextBackground,
  3379.              BackgroundOutTextXY
  3380.  
  3381.  
  3382. PAGE - variable
  3383. ───────────────
  3384.  
  3385. Function   : Holds the number of the actual drawing page
  3386.  
  3387. Declaration: VAR PAGE:WORD
  3388.  
  3389. Description: AniVGA uses a page flipping approach. Basically this means that it
  3390.              alternates between using page 0 and page 1 for its display.
  3391.              Although this mechanism should be transparent for the user, AniVGA
  3392.              provides you with the page number of the actual drawing page in
  3393.              "PAGE". Note that this number specifies always the invisible page:
  3394.              when PAGE=0, then the actual _displayed_ page is page 1 and vice
  3395.              versa (AniVGA always works on the invisible page!).
  3396.  
  3397. Note (!)   : Only _read_ this value, never assign a new value to it!
  3398.  
  3399.  
  3400. PAGEADR - variable
  3401. ──────────────────
  3402.  
  3403. Function   : Holds the segment address of the actual drawing page PAGE
  3404.  
  3405. Declaration: VAR PAGEADR:WORD
  3406.  
  3407. Description: As already mentioned, there are four graphic pages, numbered from
  3408.              0 to 3. The start addresses of these four pages are used by AniVGA
  3409.              and normally the user should not need to reference them, but with
  3410.              PAGEADR at least the address of the actual (invisble) graphic page
  3411.              PAGE is available in PAGEADR.
  3412.  
  3413. Note (!)   : Only use this variable to _read_ its value, never change it!
  3414.              Although this 16-bit-value represents only the segment part of the
  3415.              complete address, it is the whole address: the address is norma-
  3416.              lized in such a way that the offset part is always zero.
  3417.  
  3418. See also   : PAGE
  3419.  
  3420.  
  3421. PageGetPixel - function
  3422. ───────────────────────
  3423.  
  3424. Function   : Returns the color value of the specified point
  3425.  
  3426. Declaration: FUNCTION PageGetPixel(x,y:INTEGER; pa:WORD):BYTE; FAR;
  3427.  
  3428. Description: If the point at the virtual coordinates (x,y) and graphic page
  3429.              "pa" lies on the screen (i.e.: in the range (0,0)..(319,199) in
  3430.              absolute coordinates), this routine will return its color, if it
  3431.              is offscreen, the function returns zero.
  3432.              "pa" should be one of the values 0, 1 or BACKGNDPAGE (=2). (For
  3433.              special purposes, SCROLLPAGE (=3) will be accepted, too)
  3434.  
  3435. Note       : - If you want to read a pixels' color from the _visible_ page, you
  3436.                have to remember that it is the opposite of the _actual_ page
  3437.                (that is, you have to use "1-PAGE" as page number).
  3438.              - Although only values of 0, 1, BACKGNDPAGE (=2) and SCROLLPAGE
  3439.                (=3) make sense as "pa" values, the routine doesn't check that
  3440.                (for improved speed)
  3441.              - For that, the routine _doesn't_ return Err_InvalidPagenumber or
  3442.                something similiar in ERROR!
  3443.  
  3444. See also   : Background, Coordinates, GetPixel
  3445.  
  3446.  
  3447. PagePutPixel - procedure
  3448. ────────────────────────
  3449.  
  3450. Function   : Plots a point at a specified page
  3451.  
  3452. Declaration: PROCEDURE PagePutPixel(x,y:INTEGER; color:BYTE; pa:WORD); FAR;
  3453.  
  3454. Description: This routine is very similiar to PutPixel(), but it lets you
  3455.              specify explicitly on which graphic page the point shall be drawn.
  3456.              (x,y) specify the virtual coordinates of the point to be drawn in
  3457.              color "color". If this point lies onscreen (i.e.: its absolute
  3458.              coordinates are between (0,0)..(319,199)), it will be drawn on the
  3459.              specified page "pa", which must have one of the values 0, 1,
  3460.              BACKGNDPAGE (=2) or SCROLLPAGE (=3). The latter ones only make
  3461.              sense if STATIC is used as background mode.
  3462.  
  3463. Note       : - Don't forget that this routine works with virtual coordinates.
  3464.              - Note also that the point is _not_ drawn automatically on the
  3465.                background page if pa=0 or pa=1, thus it will be visible exactly
  3466.                one animation cycle (and be overdrawn by the background image
  3467.                then).
  3468.              - Because of AniVGA's working scheme, you probably want to use
  3469.                this routine AFTER calling Animate() (else, your point would be
  3470.                overdrawn by the background image immediately) if pa=1-PAGE.
  3471.                If you want to draw the point at the _visible_ page, remember
  3472.                that it is the "opposite" of the _actual_ drawing page, i.e.:
  3473.                you have to use "1-PAGE" for "pa".
  3474.              - For improved speed, the routine _doesn't_ check the "pa"
  3475.                variable to have a valid value, so there will be no report to
  3476.                ERROR (Err_InvalidPageNumber or the like) available!
  3477.                It remains your responsibility to assure a proper value for pa!
  3478.  
  3479. See also   : BackgroundPutPixel, PutPixel, coordinates, How AniVGA works
  3480.  
  3481.  
  3482. Palette, PaletteEntry, PalettePtr - type
  3483. ────────────────────────────────────────
  3484.  
  3485. Function   : Supplies user with proper internal data types
  3486.  
  3487. Declaration: TYPE PaletteEntry=RECORD red,green,blue:BYTE END;
  3488.                   Palette=ARRAY[0..255] OF PaletteEntry;
  3489.                   PalettePtr=^Palette;
  3490.  
  3491. Description: Drawing colors with the EGA/VGA is quite an interesting thing!
  3492.              You probably heard that "mode $13 gives you 256 out of 262144
  3493.              colors". The key to this is the palette (or, to be precise:
  3494.              the color-look-up-table "CLUT").
  3495.              Every color (in the range 0..255) is used as a pointer into the
  3496.              CLUT; the corresponding entry consists of three bytes, which
  3497.              stand for the red/green/blue intensity of that color (in that
  3498.              order!). These three "bytes" (only the values 0..63 are valid for
  3499.              each of them) together form an "PaletteEntry". Because we have
  3500.              256 colors, a complete CLUT is made of 256 such entries: such a
  3501.              table will be called a "Palette" in AniVGA!
  3502.  
  3503. Note       : AniVGA initially assumes the default colors of mode $13.
  3504.              When you change the palette and you are using one of the display
  3505.              modes Display_SHADOW or Display_SHADOWEXACT, AniVGA must know
  3506.              this, as it must recompute its ShadowTab. "SetPalette()" takes
  3507.              care of this, so you shouldn't change palettes by other means
  3508.              than "SetPalette()" until you are absolutely sure what you are
  3509.              doing!
  3510.  
  3511.              FYI: Note also that the 256 color modes are something special:
  3512.              in all other graphic modes (the EGA's 640x350x16 for example),
  3513.              there is a second, intermediate indirection level.
  3514.              There, the color value is used as an index into a table, giving
  3515.              a value between 0..63. This value is used again as an index into
  3516.              a second table which holds the triples ("PaletteEntries")
  3517.              mentioned above. The first table is called the palette, the second
  3518.              is the CLUT. In the 256 color modes, only the CLUT is used, but
  3519.              few of us ever heard of CLUTs! Because there is no way to confuse
  3520.              things in AniVGA, I decided to use the term "palette"!
  3521.  
  3522. See also   : SetShadowTab, ShadowTab, DefaultColors, SetPalette, GetPalette
  3523.  
  3524.  
  3525. Palette (*.PAL) files - information
  3526. ───────────────────────────────────
  3527.  
  3528. Palette files generated by GRAB and MAKES make it possible to use different
  3529. colors than the BIOS default values, just by issuing a LoadPalette()-call.
  3530. Their internal format is the simplest possible: each color consists of three
  3531. bytes, specifying the RGB-values (in that order), where each value can reach
  3532. from 0 (darkest) to 63 (brightest), e.g.: a bright red would be coded as
  3533. (63,0,0).
  3534. LoadPalette() reads in a complete palette - equally, if it is 3*16 bytes in
  3535. size or the max. 3*256 bytes for a complete 256 color palette, but it is wise
  3536. to use complete 256 color palettes, because otherwise you soon get confused,
  3537. - don't say I didn't warn you!
  3538.  
  3539. See also   : LoadPalette(), Palette
  3540.  
  3541.  
  3542. PutImage - procedure
  3543. ────────────────────
  3544.  
  3545. Function   : Pastes a formerly copied image to the screen
  3546.  
  3547. Declaration: PROCEDURE PutImage(x,y:INTEGER; p:POINTER; pa:WORD); FAR;
  3548.  
  3549. Description: PutImage() is the counterpart of GetImage(): use GetImage() to
  3550.              copy part of the screen and PutImage to paste it somewhere. (x,y)
  3551.              is the upper left corner of the destination (in _virtual_ coordi-
  3552.              nates), "p" is the pointer given by GetImage() and "pa" is the
  3553.              number of the graphic page (0, 1, BACKGNDPAGE (=2) or SCROLLPAGE
  3554.              (=3)) of the destination.
  3555.              If p equals NIL, the routine does nothing at all; this is useful
  3556.              because you can PutImage() directly on the result of a GetImage()
  3557.              call without further checking for clippings, although you should
  3558.              be careful by doing so: you don't get a "handle" this way which
  3559.              you could use to free up the occupied memory again!
  3560.              (See FreeImageMem() for more about that)
  3561.  
  3562. Note       : - Like GetImage(), this routine also works only when the _virtual_
  3563.                coordinates translate into _absolute_ coordinates in the range
  3564.                of 0..319, 0..199, that is: they must lie on the visible part of
  3565.                the screen, everything else is clipped off.
  3566.              - Possible ERROR-values returned are: Err_InvaliPageNumber
  3567.  
  3568. See also   : GetImage, FreeImageMem, coordinates
  3569.  
  3570.  
  3571. PutPixel - procedure
  3572. ────────────────────
  3573.  
  3574. Function   : Plots a point
  3575.  
  3576. Declaration: PROCEDURE PutPixel(x,y:INTEGER; color:BYTE); FAR;
  3577.  
  3578. Description: (x,y) specify the virtual coordinates of the point to be drawn in
  3579.              color "color". If this point lies onscreen (i.e.: its absolute
  3580.              coordinates are between (0,0)..(319,199)), it will be drawn on the
  3581.              visible page 1-PAGE.
  3582.  
  3583. Note       : This routine is not the same as TurboPascal's one: it works with
  3584.              virtual coordinates! Note also that the point is _not_ drawn on
  3585.              the background page, thus it will be visible for exactly one ani-
  3586.              mation cycle (and be overdrawn by the background image then).
  3587.              Because of AniVGA's working scheme, you probably want to use this
  3588.              routine AFTER calling Animate() (your point will then be visible
  3589.              until the next call to Animate()).
  3590.  
  3591. See also   : BackgroundPutPixel, PagePutPixel, coordinates, How AniVGA works
  3592.  
  3593.  
  3594. PutTile - procedute
  3595. ───────────────────
  3596.  
  3597. Function   : "Pastes" a tile into the background image
  3598.  
  3599. Declaration: PROCEDURE PutTile(x,y:INTEGER; TileNr:BYTE); FAR;
  3600.  
  3601. Description: After you have defined a background scrolling area, you can use to
  3602.              PutTile() to arrange them as wanted to build your background image.
  3603.              (x,y) is the virtual coordinate where you want the tile "TileNr"
  3604.              to be placed.
  3605.              (x,y) will be changed to be a multiple on 16 in each direction
  3606.              and must then lie in the range (BackX1,BackY1)..(BackX2,BackY2).
  3607.  
  3608. Note       : - Of course, this routine only makes sense when you use background
  3609.                mode SCROLLING!
  3610.              - (x,y) will be drawn to the upper left to fall on the grid.
  3611.              - Possible ERROR-values returned are: Err_InvalidCoordinates
  3612.  
  3613. See also   : background, tile, SetBackgroundScrollRange, coordinate, BackX1,
  3614.              BackX2, BackY1, BackY2, GetTile
  3615.  
  3616.  
  3617. Screen - procedure
  3618. ──────────────────
  3619.  
  3620. Function   : Chooses the display page.
  3621.  
  3622. Declaration: PROCEDURE Screen(pa:WORD) FAR;
  3623.  
  3624. Description: Call Screen() with a value between 0 and 3 which tells the routine
  3625.              to which graphic page it should switch. This is done by repro-
  3626.              gramming the VGA start address registers. For a flickerfree dis-
  3627.              play, this switching is synchronized to the display enable signal.
  3628.  
  3629. Note (!)   : - You should not use this routine if you are not absolutely sure
  3630.                what you are doing! Be aware that AniVGA relies on the fact that
  3631.                the actual drawing page is PAGE and its segment address is in
  3632.                PAGEADR while the actually visible page is 1-PAGE!
  3633.              - Although it makes little sense to apply this routine to graphic
  3634.                pages other than 0 or 1, it is possible to set "pa" to 2 (=BACK-
  3635.                GNDPAGE) or 3 (=SCROLLPAGE).
  3636.  
  3637. See also   : PAGE, PAGEADR, InitGraph
  3638.  
  3639.  
  3640. ScrollPage - constant
  3641. ─────────────────────
  3642.  
  3643. Function   : Holds the page number of the backround page
  3644.  
  3645. Declaration: CONST SCROLLPAGE=3;
  3646.  
  3647. Description: When using background mode SCROLLING, BackGndPage specifies the
  3648.              page number of the tile buffer used to build up the background
  3649.              image for animations.
  3650.  
  3651. Note (!)   : - Use of this constant only makes sense when using background
  3652.                mode SCROLLING!
  3653.              - AniVGA allows to treat pages 2 and 3 (=BACKGNDPAGE and
  3654.                SCROLLPAGE) as normal graphic pages. This is convenient for the
  3655.                advanced user who wants to play special tricks on AniVGA (the
  3656.                routine IntroScroll() is an example for this).
  3657.                However, you should not forget, that *normaly*, pages 2 and 3
  3658.                have a special purpose in AniVGA and shouldn't be used by you.
  3659.  
  3660. See also   : BackGndPage, Background, IntroScroll
  3661.  
  3662.  
  3663. SetAnimateWindow - procedure
  3664. ────────────────────────────
  3665.  
  3666. Function   : Restricts animations to a screen window
  3667.  
  3668. Declaration: PROCEDURE SetAnimateWindow(x1,y1,x2,y2:INTEGER); FAR;
  3669.  
  3670. Description: By default, the complete screen is set to display animations
  3671.              (this is equivalent to SetAnimateWindow(0,0,XMAX,YMAX) ).
  3672.              By using this procedure, you may restrict animations to a
  3673.              smaller "window" of your screen: (x1,y1) and (x2,y2) are the
  3674.              upper left and lower right corner of this window, specified
  3675.              as *absolute* coordinates of course.
  3676.              The best way to imagine the functionality is this: think of a
  3677.              black sheet of paper, 320x200 units in size, covering your
  3678.              monitor display. SetAnimateWindow() cuts a hole in this paper
  3679.              so that you may look through it to see the animations taking
  3680.              place at the screen. The resting parts of that sheet remain
  3681.              completely untouched by AniVGA and under your responsibility.
  3682.              Line- and pixeldrawing routines may restrict ("clip") their
  3683.              outputs to this animation window --you can control that by
  3684.              using the boolean variable "WinClip".
  3685.              If for some reason you want some sprites _not_ to be clipped,
  3686.              you may use SetSplitIndex() to tell AniVGA which sprites should
  3687.              be clipped and which should not.
  3688.  
  3689. Note (!)   : - As said, the window is defined with absolute coordinates
  3690.              - Its boundaries must meet some restrictions: x1 and the window
  3691.                width itself (=x2+x1-1) must be multiples of 4 and the window
  3692.                must be at least 32x32 points in size.
  3693.              - The routine tries to round the coordinates given appropriately
  3694.                and reflects the chosen values in WinXMIN, WinYMIN, WinWidth and
  3695.                WinHeight. (If it fails, you will get an Err_InvalidCoordinates
  3696.                error).
  3697.              - Due to this rounding effects, rely upon the Win* variables
  3698.                instead of the original values you gave to the routine
  3699.              - This routine works with both STATIC and SCROLLING backgrounds!
  3700.                Although its use is more obvious with SCROLLING backgrounds, it
  3701.                makes sense to use it in mode STATIC, too: by making the area to
  3702.                to be cared about smaller, AniVGA may become faster.
  3703.              - Don't confuse this routine with SetBackgroundScrollRange()!
  3704.                SetAnimateWindow() defines what part of your (real) monitor
  3705.                shall be treated as window to your animations while
  3706.                SetBackgroundScrollRange() is a routine for background mode
  3707.                SCROLLING to define which virtual area of the coordinate space
  3708.                shall be used for tiling!
  3709.  
  3710. See also   : UpdateOuterArea, Win*, SetSplitIndex
  3711.  
  3712.  
  3713. SetBackgroundMode - procedure
  3714. ─────────────────────────────
  3715.  
  3716. Function   : Chooses one of the possible background modes of AniVGA
  3717.  
  3718. Declaration: PROCEDURE SetBackgroundMode(mode:BYTE); FAR;
  3719.  
  3720. Description: AniVGA has two possible ways of handling background you can choose
  3721.              of: "STATIC" or "SCROLLING" backgrounds with several advantages
  3722.              and disadvantages, each (see background). Specify the mode you
  3723.              want to use in the "mode" variable.
  3724.  
  3725. Note       : - Default value set by AniVGA is STATIC.
  3726.              - Possible ERROR-values returned are: Err_InvalidMode
  3727.  
  3728. See also   : background
  3729.  
  3730.  
  3731. SetBackgroundScrollRange - procedure
  3732. ────────────────────────────────────
  3733.  
  3734. Function   : Specifies the scrollable background area in mode SCROLLING
  3735.  
  3736. Declaration: PROCEDURE SetBackgroundScrollRange(x1,y1,x2,y2:INTEGER) FAR;
  3737.  
  3738. Description: (x1,y1) is the upper left corner of the background scroll area,
  3739.              (x2,y2) the lower right corner (all virtual coordinates).
  3740.              AniVGA will round the points given to fit on a grid with mesh 16,
  3741.              that is, x1,y1,x2,y2 will be changed to be all multiples of 16.
  3742.              These new values will be stored in the (global) variables BackX1,
  3743.              BackY1, BackX2, BackY2 for further use.
  3744.              Besides that, XTiles and YTiles will hold the width and height of
  3745.              the choosen background area in tiles.
  3746.  
  3747. Note       : - You can read the Back??-variables for your information, but
  3748.                don't change them!
  3749.              - Of course, this routine only makes sense when you are going to
  3750.                use SCROLLING as background mode.
  3751.              - The upper left corner (x1,y1) will be dragged to the upper left,
  3752.                the lower right corner (x2,y2) to the lower right to fall on the
  3753.                grid.
  3754.              - Don't forget that the tile memory is limited; you can't select
  3755.                an area bigger than MaxTiles (=10000) tiles, that is more than
  3756.                2560000 pixels².
  3757.              - Possible ERROR-values returned are: Err_InvalidCoordinates and
  3758.                Err_BackgroundToBig
  3759.              - Don't confuse this routine with SetAnimateWindow()
  3760.  
  3761. See also   : background, tiles, PutTile, SetAnimateWindow
  3762.  
  3763.  
  3764. SetCycleTime - procedure
  3765. ────────────────────────
  3766.  
  3767. Function   : Defines the maximum animation speed
  3768.  
  3769. Declaration: PROCEDURE SetCycleTime(milliseconds:WORD); FAR;
  3770.  
  3771. Description: There are lots of PC-compatible machines with a broad range of
  3772.              clock rates, wait states and different speeds of their graphic
  3773.              cards. With this routine you can set the time an animation cycle
  3774.              has to last at least: at the very end of Animate, the routine
  3775.              checks whether at least "milliseconds" milliseconds have been past
  3776.              since the last call to this routine and waits if necessary.
  3777.              If you give 0 milliseconds as an argument or your machine is not
  3778.              (at least) an AT class machine, there will be no such time control
  3779.              mechanism and the animation will always take part at the maximal
  3780.              speed on the specific machine (this is also the default value).
  3781.  
  3782.              For example: "SetCycleTime(100);" would restrict the animation
  3783.              rate even on the fastest 80586 machines to at most 1sec/100msec
  3784.              = ten frames per second.
  3785.  
  3786. Note (!)   : - Because there is no such high precision timer on PC/XT computers
  3787.                as required, SetCycleTime() is ignored on these machines.
  3788.                Anyway, this should be not to hard because these computers are
  3789.                normally that slow that they would not have been slowed down
  3790.                either.
  3791.              - The accuracy of this timing mechanism is better than 1 milli-
  3792.                second.
  3793.  
  3794.  
  3795. SetModeByte - procedure
  3796. ───────────────────────
  3797.  
  3798. Function   : Specifies the way a sprite will be displayed
  3799.  
  3800. Declaration: PROCEDURE SetModeByte(Sp:WORD; M:BYTE); FAR;
  3801.  
  3802. Description: This routine assigns one of the possible display methods "M"
  3803.              (Display_NORMAL, Display_FAST, Display_SHADOW,
  3804.               Display_SHADOWEXACT)
  3805.              to the specified spriteLOADnumber "Sp".
  3806.  
  3807. Note       : - Because this kind of information is stored directly inside the
  3808.                sprite data, the sprite must have been loaded already for this
  3809.                routine to work.
  3810.              - For the same reason, the routine works on spriteLOADnumbers,
  3811.                not sprite numbers (>gee, again!<): a display method set for one
  3812.                spriteLOADnumber will affect all sprites with that LOADnumber!
  3813.                Most often, that is okay (e.g.: if you use the sprite of a foot-
  3814.                ball player ten times, it is quite normal to use the same dis-
  3815.                play mode for all ten players!), if you really must use a sprite
  3816.                with two different display methods at the same time, you can use
  3817.                the following trick: load the sprite's data a second time into
  3818.                memory, using a different spriteLOADnumber. For this new copy,
  3819.                you can use another display mode.
  3820.              - Possible ERROR-values returned are: Err_InvalidSpriteNumber and
  3821.                Err_InvalidMode
  3822.  
  3823. See also   : SpriteLoadNumber, SpriteNumber, Display methods, GetModeByte
  3824.  
  3825.  
  3826. SetOffscreenTile - procedure
  3827. ────────────────────────────
  3828.  
  3829. Function   : Defines the tile to be used outside the specified scroll range
  3830.  
  3831. Declaration: PROCEDURE SetOffscreenTile(TileNr:BYTE); FAR;
  3832.  
  3833. Description: When you use background mode SCROLLING and have set up a scroll
  3834.              range (via SetBackgroundScrollRange() ), all tiles _within_ that
  3835.              region are specified by your settings done with PutTile().
  3836.              However, AniVGA must know what to draw when it has to display
  3837.              areas _outside_ that "window": you can choose that tile with
  3838.              SetOffscreenTile().
  3839.              Example: You set your scrollable background range by issuing
  3840.              SetBackgroundScrollRange(-500,-500,1000,1000) and used PutTile()
  3841.              to define that tiles 0..10 (say) should be used inside that
  3842.              window (-500,-500,1000,1000) in some specific order. If you want
  3843.              that everything outside the window should be painted with tile
  3844.              6 (say), you would tell AniVGA so by calling SetOffscreenTile(6)
  3845.  
  3846. Note       : - The default value set by AniVGA is 0
  3847.              - Of course, using this procedure only makes sense when using
  3848.                background mode SCROLLING!
  3849.  
  3850. See also   : SetBackgroundScrollRange, PutTile, Background
  3851.  
  3852.  
  3853. SetPalette - procedure
  3854. ──────────────────────
  3855.  
  3856. Function   : Changes the VGA's color values
  3857.  
  3858. Declaration: PROCEDURE SetPalette(pal:Palette; update:BOOLEAN); FAR;
  3859.  
  3860. Description: You can use this procedure to change the color values of the VGA's
  3861.              256 colors by supplying an appropriate palette.
  3862.              "update" tells the procedure whether it should recompute its
  3863.              internal "ShadowTab" or not; if you use one of the two display
  3864.              modes Display_SHADOW or Display_SHADOWEXACT you must set this
  3865.              value to TRUE or the shadow areas will show "wrong" colors
  3866.              (namely the old ones *before* changing the palette). If you don't
  3867.              use shadowing (or change colors in a way so that using the old
  3868.              shadow is okay), you can use FALSE and save some time.
  3869.  
  3870. Note       : - SetPalette automatically updates "ActualColors" to reflect the
  3871.                changes made; although you don't have to use the variable
  3872.                "ActualColors" as first parameter of this procedure, you are
  3873.                recommended to do so, that is
  3874.                 a) make your color changes to ActualColors[]
  3875.                 b) call SetPalette(ActualColors,TRUE|FALSE)
  3876.                This way, you will save some time and the memory requirements
  3877.                for an additional palette
  3878.              - If you messed up things, use "SetPalette(DefaultColors,TRUE)" to
  3879.                return to the default values.
  3880.              - You must be in graphic mode already or strange things may happen
  3881.                (at least, you won't get the colors you intented...)
  3882.                To state in otherwise: call this routine _after_ having called
  3883.                InitGraph() and _before_ calling CloseRoutines()!
  3884.  
  3885. See also   : GetPalette, Palette, LoadPalette, ActualColors
  3886.  
  3887.  
  3888. SetShadowTab - procedure
  3889. ────────────────────────
  3890.  
  3891. Function   : Set the amount of shadowing in display modes Display_SHADOW and
  3892.              or Display_SHADOWEXACT
  3893.  
  3894. Declaration: PROCEDURE SetShadowTab(brightness:BYTE); FAR;
  3895.  
  3896. Description: Whenever a sprite is drawn in Display_SHADOW / Display_SHADOWEXACT
  3897.              mode, AniVGA must know how much darker these shadow areas should
  3898.              be, compared with the brightness of the original (not-shadowed)
  3899.              colors.
  3900.              This data is held in the table ShadowTab and is set by default to
  3901.              70% of the colors original brightness. However, you can use this
  3902.              routine to provide more or less darker shadow areas: "brightness"
  3903.              is the percentage of the colors original brightness which shall
  3904.              remain, e.g.: brightness=0 would mean every shadow is completely
  3905.              black, brightness=100 is the original color as shadow (not darken-
  3906.              ed at all), brightness=40 will darken every color by 100-40=60%,
  3907.              etc.
  3908.  
  3909. Note (!)   : - SetShadowTab() bases its computation on the actually displayed
  3910.                colors, held in the table "ActualColors"
  3911.              - This routine takes app. 1s on an 8MHz AT. This can be quite a
  3912.                "long" time when you are in midst of a smooth animation sequence
  3913.                -or doesn't bother you at all (e.g., in the very beginning of
  3914.                your program) - this depends on your applications!
  3915.              - The argument will be only approximated: the algorithm computes
  3916.                the 256 color values needed precisely and matches them as close
  3917.                as possible to the 256 colors actually set.
  3918.                Note that the palette registers of the VGA card *won't* be
  3919.                changed at all! AniVGA still works with the default VGA palette
  3920.                of the BIOS (or whatever values you set); what it does is
  3921.                solely creating an internal color look-up-table!
  3922.              - Possible ERROR-values returned are: Err_InvalidPercentage
  3923.  
  3924. See also   : ShadowTab, ActualColors, Display modes, SetModeByte
  3925.  
  3926.  
  3927. SetSplitIndex - procedure
  3928. ─────────────────────────
  3929.  
  3930. Function   : Define which sprites should be clipped to the animation window
  3931.  
  3932. Declaration: PROCEDURE SetSplitIndex(number:INTEGER); FAR;
  3933.  
  3934. Description: If you defined an animation window (using SetAnimateWindow() ),
  3935.              all sprites will automagically be clipped properly at the
  3936.              boundaries of this window. However, you may think of a few
  3937.              situations where you want to disable this clipping, so you can
  3938.              draw a sprite _outside_ the animation window.
  3939.              You can telling AniVGA which sprites should be clipped and which
  3940.              should not by using SetSplitIndex(number): all sprites
  3941.              SPRITEN[0..number]      will not be clipped to the window and
  3942.              SPRITEN[number+1..NMAX] will still be clipped
  3943.              To turn on clipping for all sprites again, just call this
  3944.              procedure with an argument <0 or >NMAX
  3945.  
  3946. Notes      : - Default value is: all sprites clipped
  3947.              - Of course, clipping at the *physical* screen boundaries won't
  3948.                be affected in any way!
  3949.  
  3950. See also   : SetAnimateWindow, WinClip
  3951.  
  3952.  
  3953. SetSpriteCycle - procedure
  3954. ──────────────────────────
  3955.  
  3956. Function   : Link spriteLOADnumbers together to form a sprite cycle
  3957.  
  3958. Declaration: PROCEDURE SetSpriteCycle(nr,len:WORD); FAR;
  3959.  
  3960. Description: "nr" is the first spriteLOADnumber to be included in the sprite
  3961.              cycle and "len" entries (i.e.: from "nr" to "nr+len-1") should be
  3962.              tied together.
  3963.              The routine will then set the according NextSprite[] entries to
  3964.              build this cycle: nr -> nr+1 -> nr+2 -> ... -> nr+len-1 -> nr
  3965.  
  3966. Note       : - The routine uses spriteLOADnumbers, _not_ sprite numbers!
  3967.              - If you want to link sprite(loadnumber)s which do not have conse-
  3968.                cutive (load)numbers, you must do that by setting NextSprite[]
  3969.                accordingly.
  3970.  
  3971. See also   : Sprite cycles, NextSprite
  3972.  
  3973.  
  3974. ShadowTab - "procedure"
  3975. ───────────────────────
  3976.  
  3977. Function   : Table for translating sprite colors into others
  3978.  
  3979. Declaration: PROCEDURE ShadowTab; FAR;
  3980.  
  3981. Description: If the display mode "Display_SHADOW" is set for a physical
  3982.              sprite, its colors will depend not on the values stored in the
  3983.              sprite itself, but on the values found on the screen at the place
  3984.              where the sprite shall be drawn: every pixel of the sprite will
  3985.              become darkened by substituting its corresponding color against
  3986.              the color stored in this color table. (Mode "Display_SHADOWEXACT"
  3987.              behaves the same, but shadowing will take place only at points
  3988.              with sprite color <>0 - that's the whole difference).
  3989.              At startup, this table is set to make shadows be approximately
  3990.              70% the brightness of the original colors, but you can adjust
  3991.              this with the routine SetShadowTab() if this value is not sui-
  3992.              table for your application.
  3993.              You can even supply a completely different color table (for
  3994.              special effects?).
  3995.              To do so, define an array "[0..255] of byte" (you should use the
  3996.              predefined TYPE ColorTable for this), containing for each color
  3997.              of the standard palette its substitute (e.g. setting array
  3998.              element [8]:=13 would mean: "replace every pixel in the shadow
  3999.              area with color 8 against a pixel with color 13") and overwrite
  4000.              the original color table by issuing the command
  4001.              "MOVE(my_array,@ShadowTab^,256)"
  4002.  
  4003. Note       : - Although this table is declared as a procedure, it really is
  4004.                data, not code; so don't call it!
  4005.              - There can be only _one_ color table and it is only active in
  4006.                display modes "Display_SHADOW" or "Display_SHADOWEXACT".
  4007.  
  4008. See also   : SetShadowTab, Display modes, SetModeByte
  4009.  
  4010.  
  4011. SHOWPIC - utility
  4012. ─────────────────
  4013.  
  4014. This is a _very_ small utility program to display a *.PIC-file on the screen.
  4015. (As a matter of fact, someone asked for a way to do so and as it could be
  4016.  done that easily, I just couldn't resist typing it in... :) )
  4017. Call the program with the complete name of the *.PIC-file to display and
  4018. (optionally) the name of the palette file to be used as second parameter.
  4019. If you omit the palette file name, the program will use the VGA's default
  4020. palette.
  4021. Example: "SHOWPIC FRACTAL1.PIC FRACTAL.PAL" would load the picture
  4022. FRACTAL1.PIC and use the palette FRACTAL.PAL to display it.
  4023. Press any key to return to text mode again.
  4024.  
  4025. See also   : MAKES
  4026.  
  4027.  
  4028. SPRITE, Spritenumbers, Spriteloadnumbers - information
  4029. ──────────────────────────────────────────────────────
  4030.  
  4031. A sprite is the basic data element used in AniVGA. Technically spoken, it is
  4032. nothing more then a two-dimensional array of bytes which becomes copied to the
  4033. screen positions needed, but it is far more comprehensive to think about it as
  4034. a photograph of a figure which can be pasted to the screen whereever you want.
  4035. To distinguish between different sprites, we use natural numbers, but whenever
  4036. we talk about "sprites", we are somehow inaccurate:
  4037. You should notice that there are two kinds of "sprite numbers" which should
  4038. not be mixed up: one is a spriteLOAD number and represents a handle to the
  4039. (physical) sprite data, while the other (normally termed "sprite number") is
  4040. a logical number to address the sprite data.
  4041. Yet, most often it is clear from the context, which meaning is intended:
  4042. For a simple example: if you are going to animate a soccer team, you would
  4043. need 11 sprites for the player - but they all have the same shape. This means,
  4044. you only have to load one sprite (-> you need 1 spriteLOAD number), but need
  4045. 11 copies of that image to move around the screen (-> you need 11 sprite
  4046. numbers).
  4047. (See section "How AniVGA works" for more about that)
  4048. You can design sprites with the help of the spritemaker-tool MAKES, by using
  4049. GRAB to capture and convert graphic screens from other graphic applications
  4050. or write your own tools for that (it's really not that difficult you think
  4051. it is...).
  4052.  
  4053. See also   : sprite format, How AniVGA works
  4054.  
  4055.  
  4056. SPRITE CYCLES - information
  4057. ───────────────────────────
  4058.  
  4059. Often, you don't want to have a single picture as sprite, but a sequence of
  4060. them which should loop forever. For example, let's assume that you use a torch
  4061. as an animation object in your application and you want it to have a flicker-
  4062. ing flame.
  4063. You would start to draw 5 (say) pictures, which -repeatedly displayed one
  4064. after another- would make the impression of your flickering torch. But within
  4065. your application, you still want to handle these five different images as one
  4066. single object - namely the sprite "torch".
  4067. To do so, you can use a capability of AniVGA, called a "sprite cycle": load
  4068. the five images as (physical) sprites and tie their loadnumbers together to
  4069. form that sequence!
  4070. The easiest way to do that would be to load the images with consecutive
  4071. numbers and use the SetSpriteCycle() procedure to form the sprite cycle (see
  4072. there).
  4073. Note that we are talking about linking spriteLOADnumbers here: when you have
  4074. built such a cycle for your torch and you want to use 10 torches in your
  4075. program, you surely want that each of them behaves the same, that is: they all
  4076. should show a flickering flame by using that sprite cycle.
  4077. For this reason, AniVGA uses spriteLOADnumbers, so that every instantiation of
  4078. a spriteLOADnumber (i.e.: a SpriteN[]-entry) belonging to a cycle will lead to
  4079. a sprite cycle for this sprite! (Tip: in out torches example, it would be wise
  4080. to use different starting values for the 10 torches, so that they do not
  4081. flicker "in phase")
  4082. A small detail at last: if you defined a sprite cycle to be a->b->c->a->...,
  4083. and initialized a SpriteN[]-entry to "a", then the first sprite displayed at
  4084. the screen will be "b" instead of "a" - why?
  4085. Well, AniVGA handles sprite cycles in the Animate() routine and thus has two
  4086. possibilities to update the SpriteN[]-table (by issuing a "SpriteN[] :=
  4087. NextSprite[SpriteN[]]" command): _before_ drawing the sprites or _afterwards_.
  4088. But when it does _after_ drawing the sprites, the sprites displayed on your
  4089. screen (=the old SpriteN[] values before doing the above command) are incon-
  4090. sistent to the according numbers actually held in the SpriteN[]-table!
  4091. This could lead to problems (e.g.: when you do a HitDetect() after calling
  4092. Animate()). Although this could be circumvented by a special grouping of sub-
  4093. routine calls, it is far more convenient to update the SpriteN[]-table
  4094. _before_ drawing the sprites.
  4095. The only drawback with this method is the one stated in the beginning: not the
  4096. SpriteN[]-entry supplied by you will be drawn, but its "successor"
  4097. NextSprite[SpriteN[]]!
  4098. However, most often that won't be that bad and *if* it would, you still could
  4099. compensate for it by using the sprite's predecessor (in the above example, you
  4100. would use "c", as it is the predecessor of "a", to display "a").
  4101.  
  4102.  
  4103. SPRITE FORMAT - information
  4104. ───────────────────────────
  4105.  
  4106. As already said, a sprite is nothing more then a two-dimensional array of
  4107. bytes which becomes copied to the screen positions needed.
  4108. For quick animations, the data should be stored in a format which causes few
  4109. and simple transformation steps when accessing the data, but it is hard to
  4110. keep up with that principle, because the graphic mode used is "planed".
  4111. This means that points are _not_ stored sequentially into the graphics memory,
  4112. but in a rather strange way: every 4 points use the same address, but lie in
  4113. different "bitplanes". To cut it short: clipping and drawing sprites is hell
  4114. therefore (and surely one reason why there are so less tools for this mode)
  4115. and AniVGA uses a very special format to store a sprite (= *.COD-files):
  4116.  
  4117.       0..1   DW offset to Plane_0_Data (points with x-coord. MOD 4=0)
  4118.       2..3   DW offset to Plane_1_Data (points with x-coord. MOD 4=1)
  4119.       4..5   DW offset to Plane_2_Data (points with x-coord. MOD 4=2)
  4120.       6..7   DW offset to Plane_3_Data (points with x-coord. MOD 4=3)
  4121.       8..9   DW sprite width (DIV 4), rounded up if not dividable by 4
  4122.       10..11 DW sprite height in lines
  4123.       12..15 DB 1,2,4,8      ; constants (translate-table)
  4124.       16..17 DW SpriteLength ; length of this sprite file
  4125.       18..37 DW 10 dup(?)    ; reserved area for future use
  4126.       38..39 DB 'K','R'      ; code for "this is a sprite file"
  4127.       40     DB 1            ; version
  4128.       41     DB 0            ; default display mode (0=Display_NORMAL)
  4129.       42..43 DW offset pointer to left boundary table
  4130.       44..45 DW offset pointer to right boundary table
  4131.       46..47 DW offset pointer to top boundary table
  4132.       48..49 DW offset pointer to bottom boundary table
  4133.       50..SpriteLength-1: boundary- and plane data tables
  4134.  
  4135. (If you should wonder why all pointers are only 16 bit long: the maximal size
  4136.  of one sprite is 64k, so offset pointers are sufficient.
  4137.  Another trick is that AniVGA loads sprites at segment boundaries; for that,
  4138.  you don't have to distinguish between "relative offsets" and "offset poin-
  4139.  ters": if normalized segment addresses (=offset part is ε [0..15]) are used
  4140.  to address sprites, the offset part is always 0, so the two terms are
  4141.  identical!)
  4142.  
  4143. The Plane_?_Data tables consist of the points of the sprite (1 pixel = 1 byte);
  4144. if the sprite width is 12 pixels (say), then each table would hold 12/4=3 bytes
  4145. for each of the sprite's rows:
  4146. Plane_0_Data = color of pixels 0,4,8 of 1. sprite row
  4147.                color of pixels 0,4,8 of 2. sprite row
  4148.                ...
  4149. Plane_1_Data = ditto, for pixels 1,5,9
  4150. Plane_2_Data = ditto, for pixels 2,6,10
  4151. Plane_3_Data = ditto, for pixels 3,7,11
  4152.  
  4153. The boundary tables hold the outermost positions of the sprite:
  4154.  The left/top/right/bottom boundary table holds the leftmost/topmost/
  4155.  rightmost/bottomost pixel of each row/column/row/column (or 16000/16000/
  4156.  -16000/-16000 if none exists), respectively:
  4157. left boundary table = leftmost pixel coordinate of 1. sprite row  (or 16000)
  4158.                       leftmost pixel coordinate of 2. sprite row  (or 16000)
  4159.                       ...
  4160. Note that each entry in the boundary tables consists of a signed integer!
  4161.  
  4162. Note also that sprites are always stored as the smallest, the figure including
  4163. box (rounded up in the x-direction to the next multiple of 4), but that the
  4164. values of the "superfluous points" stored in the plane tables doesn't matter
  4165. at all (no difference which display mode is used for the sprite!), because
  4166. AniVGA uses only the bytes of the areas which belong to the _real_ sprite-
  4167. figure (AniVGA determines these parts by assuming the sprite to be "horizontal
  4168. convex" and uses the boundary tables to compute them).
  4169. (Don't worry if you do not understand these technical details now --hopefully,
  4170.  you won't need them at all).
  4171.  
  4172. See also   : MAKES, Display modes, convex, sprite library
  4173.  
  4174.  
  4175. SPRITE LIBRARY - information
  4176. ────────────────────────────
  4177.  
  4178. Sprite files can be combined to sprite libraries. The main advantage of this
  4179. is that you can reduce the number of files needed for your programs drama-
  4180. tically:
  4181. A normal program will use approximately 20..40 different sprites, so that you
  4182. would have 20..40 files only for your sprites!
  4183. But AniVGA's routine to load sprites "loadSprite()" is flexible enough to dis-
  4184. tinguish whether the file to be loaded contains one or more sprites and loads
  4185. them all.
  4186. To construct such a "sprite library" (suggested filename extension: .LIB), you
  4187. just use MSDos' COPY-command with the binary option "/B" to glue the binaries
  4188. together; for example:
  4189.  
  4190.  COPY /B sprite1.cod+d:\sprites\sprite2.cod+testspr.cod A:\mylib.lib
  4191.  
  4192. would concatenate the three sprites "sprite1.cod", "d:\sprites\sprite2.cod"
  4193. and "testspr.cod" and build the sprite library "A:\mylib.lib".
  4194.  
  4195. Note       : You can reverse this process with the UNLIB-utility.
  4196.  
  4197. See also   : UNLIB, sprite format, loadSprite
  4198.  
  4199.  
  4200. SpriteAd, SpriteSize, SpritePTR - variables
  4201. ───────────────────────────────────────────
  4202.  
  4203. Function   : Store the pointers to the sprites' data and related informations
  4204.  
  4205. Declaration: VAR SPRITEAD,SPRITESIZE:ARRAY[0..LoadMAX] OF WORD;
  4206.              VAR SPRITEPTR:ARRAY[0..LoadMAX] OF POINTER;
  4207.  
  4208. Description: Whenever you load a (physical) sprite with LOADnumber xxx, AniVGA
  4209.              stores the sprite's data somewhere in RAM and maintains a pointer
  4210.              which points to the beginning of this data as a handle to access
  4211.              the data: this handle is stored in SpriteAd[xxx] and reflects the
  4212.              segment part of the starting address of the data.
  4213.              The address and length of the memory block allocated for the
  4214.              sprite's data are stored in SpritePTR and SpriteSize, respec-
  4215.              tively.
  4216.  
  4217. Note       : - These tables have been moved to the unit's implementation part
  4218.                in version 1.2 to prevent direct accesses, so consider this
  4219.                section as informational only.
  4220.              - The contents of the segment part of the SpritePTR[] entries
  4221.                will vary from the SpriteAd[] entries, because SpritePTR[]
  4222.                holds the pointer exactly in the form returned by TP's GetMem-
  4223.                procedure while SpriteAd[] stores them normalized and evtl.
  4224.                rounded to the next segment boundary. It's also that reason,
  4225.                why the allocated block is up to 15 bytes larger then theore-
  4226.                tical necessary
  4227.  
  4228. See also   : LoadSprite, SPRITE, Sprite Format
  4229.  
  4230.  
  4231. SPRITEN, SPRITEX, SPRITEY - tables
  4232. ──────────────────────────────────
  4233.  
  4234. Function   : Hold the values of all sprites to be drawn in the next animation
  4235.              cycle.
  4236.  
  4237. Declaration: VAR SpriteN:ARRAY[0..NMAX] of Integer  (SpriteX/Y dto.)
  4238.  
  4239. Description: AniVGA is based on tables: in SpriteN[] you must declare, which
  4240.              sprites shall be drawn in the next animation step. To do that,
  4241.              store the spriteLOAD number of the sprites into the SpriteN[]-
  4242.              entries; a zero indicates that the according sprite is inactive
  4243.              and should not be displayed.
  4244.              For every active sprite (SpriteN[i]<>0), a pair of virtual coor-
  4245.              dinates in the range -16000..+16000 must be specified in the
  4246.              SpriteX[i] and SpriteY[i] entries to determine the sprites' po-
  4247.              sition on the (virtual) screen.
  4248.              These coordinates will be transformed internally into real coor-
  4249.              dinates to decide whether the sprite is onscreen and has to be
  4250.              displayed or not.
  4251.  
  4252. Note       : If you have less sprites than are allowed by the system (that is:
  4253.              less than NMAX+1), your decision what table entries you use are
  4254.              arbitrary; if for example you have only two sprites, it won't
  4255.              matter, if you use SpriteN[0] for the first one and SpriteN[1]
  4256.              for the other or vice versa, or SpriteN[123] and SpriteN[310] or
  4257.              whatever valid indices you can think of - except in one point:
  4258.              the sprites are drawn in reverse order, that means SpriteN[NMAX]
  4259.              is drawn first, then SpriteN[NMAX-1] ... SpriteN[0].
  4260.              For that, if two (or more) sprites overlap each other, the one
  4261.              with the smallest index is drawn topmost and covers the other(s).
  4262.  
  4263.              For performance reasons you should observe another rule: if you
  4264.              use different display methods for different sprites then try to
  4265.              group your sprites in such a way, that sprites with the same dis-
  4266.              play method have continous indices. As an example: if the sprites
  4267.              with (load)number 1 use one method and the ones with number 2
  4268.              another, then the sequence SpriteN[]=(...2,2,2,2,2,...,1,1,1...)
  4269.              would be better than (...2,2,1,2,...,1,2,...,1,2,...).
  4270.              This is due to the fact that whenever AniVGA has to draw a sprite
  4271.              with a display method other than the active one, it must inter-
  4272.              nally switch from one method to the other which costs some time.
  4273.  
  4274. See also   : SetModeByte
  4275.  
  4276.  
  4277. StartVirtualX, StartVirtualY - variables
  4278. ────────────────────────────────────────
  4279.  
  4280. Function   : Specify the upper left corner of the visible world
  4281.  
  4282. Declaration: CONST StartVirtualX:INTEGER=0;
  4283.                    StartVirtualY:INTEGER=0;
  4284.  
  4285. Description: When working with virtual coordinates, your screen displays only
  4286.              a very small window (320x200 points) of this "virtual screen"
  4287.              (32000x32000 points). To tell AniVGA which part of this virtual
  4288.              screen is to be displayed, you specify the upper left corner of
  4289.              the visible part in (StartVirtualX,StartVirtualY).
  4290.              For example, setting (StartVirtualX,StartVirtualY) to (100,1000)
  4291.              would define that the part of the virtual screen having x-coordi-
  4292.              nates ε [100..100+XMAX] and y-coordinates ε [1000..1000+YMAX] to
  4293.              be displayed.
  4294.  
  4295. Note       : Setting these variables doesn't affect the HitDetect-function: if
  4296.              two sprites collide outside the visible area, it will be detec-
  4297.              ted, still.
  4298.  
  4299. See also   : coordinates
  4300.  
  4301.  
  4302. Table - TYPE
  4303. ────────────
  4304.  
  4305. Function   : Supply a data type for the animation variables
  4306.  
  4307. Declaration: TYPE Table=ARRAY[0..NMAX] OF INTEGER;
  4308.  
  4309. Description: A lot of variables in AniVGA have to be of type "one entry for
  4310.              each sprite" and "Table" is the appropriate form for that.
  4311.  
  4312. Note       : -
  4313.  
  4314. See also   : SpriteX, SpriteY, SpriteN
  4315.  
  4316.  
  4317. Tile - information
  4318. ──────────────────
  4319.  
  4320. "Tiles" are graphic images, 16 pixels wide and high. They are used to define a
  4321. scrollable background image when you use SCROLLING as background mode.
  4322. Due to memory limitations, it is impossible to hold a complete background
  4323. image in memory (because virtual coordinates range 32000 pixels in x/y-direc-
  4324. tions, one would need app. 977 MB (!) RAM for that).
  4325. Instead, you may define up to 256 different tiles and then combine them to
  4326. form the graphic background, which may consist of up to MaxTiles (=10000)
  4327. tiles (using the 256 different tiles).
  4328. (A simple example for that can be found by "Background").
  4329. AniVGA stores tiles in a slightly different format then sprites internally,
  4330. but you don't have to bother your head about that: on disk, tiles have the
  4331. same format as sprites, so you can use all the utility programs to create/edit
  4332. sprites also to create/edit tiles! The only restriction you have to care about
  4333. is, that a tile has the definite size of 16 pixels in each direction (but see
  4334. the LoadTile()-function for some simplifications about even that).
  4335.  
  4336. See also   : Background, LoadTile
  4337.  
  4338.  
  4339. UNCHAIN - utility
  4340. ─────────────────
  4341.  
  4342. AniVGA uses a graphics mode unknown to TurboPascal. In fact, TP "thinks" the
  4343. mode used is BIOS mode $13 (=320x200x256x1). There is only one situation where
  4344. this assumption causes problems: when you use TP's built-in debugger (or a
  4345. standalone debugger like TD.EXE) to single-step or trace your program.
  4346. Why? Well, your program runs in AniVGA's special graphic mode -up to the point
  4347. where you stop it by some kind of breakpoint: the debugger switches to its
  4348. text mode, displays the infos you wanted. But then you tell the debugger to
  4349. continue the program and hence, it must switch back to graphics mode and
  4350. BINGO! it switches to BIOS mode $13 instead of AniVGA's graphic mode.
  4351.  
  4352. To avoid that behaviour, there is a (really) small PD utility program called
  4353. "UNCHAIN.EXE". Simply stated, prefix the command line you normally use to
  4354. invoke TP with "unchain" and that's it! For example, instead of...
  4355. TURBO.EXE myprog.pas
  4356. ...you would type in
  4357. UNCHAIN TURBO.EXE myprog.pas
  4358. Simple, ain't it? It works the same way for all other programs (TD.EXE, etc.)!
  4359.  
  4360. Of course, you also have to enable the options "Graphics screen save" and
  4361. "EGA/VGA palette save" in menu Options -> Environment -> Startup  of TP, but
  4362. I guess that goes without saying...
  4363.  
  4364.  
  4365. UNLIB - utility
  4366. ───────────────
  4367.  
  4368. Sometimes, you will want to reverse the process of building a sprite library,
  4369. that is: you want to split a sprite library into the sprite files of which it
  4370. consists.
  4371. To do that, call UNLIB with the name of the sprite library to split. UNLIB
  4372. will then create the files UNLIB000.COD, UNLIB001.COD, UNLIB002.COD,...  which
  4373. represent the sprite files wanted.
  4374. Note here that UNLIB cannot restore the original filenames you used (there is
  4375. no such entry in a sprite's header). For that, it is a good idea to write down
  4376. the names and sequence of the sprite files used in building a sprite library.
  4377. (If you didn't, you still can load every extracted sprite with MAKES, look at
  4378.  it and give it the right name then)
  4379.  
  4380. See also   : sprite library, MAKES, sprite format
  4381.  
  4382.  
  4383. UpdateOuterArea - variable
  4384. ──────────────────────────
  4385.  
  4386. Function   : Specifies if and how to update graphic area outside the animation
  4387.              window
  4388.  
  4389. Declaration: CONST UpdateOuterArea:BYTE=2;
  4390.  
  4391. Description: If you have defined an animation window (using the
  4392.              SetAnimateWindow()-procedure), AniVGA by default only handles
  4393.              that graphic area. That is, whatever you do to the screen area
  4394.              *outside* your animation window, AniVGA doesn't care: if you
  4395.              draw some objects there, it's up to you to remove them from
  4396.              there later on.
  4397.              If you draw to the background image in BACKGNDPAGE (by using
  4398.              BackgroundOutTextXY() or similiar routines), the changes done
  4399.              will not be visible to the screen image until you tell AniVGA
  4400.              to update the outer area!
  4401.              Now quite often, you will stumble into this situation:
  4402.              - you have a background image in your background page,
  4403.                surrounding your animation window (1) with some fancy
  4404.                graphics (2)
  4405.              - you draw something into the outer area, for example a high
  4406.                score (3), using BackgroundOutTextXY()
  4407.              - 50 (say) animation cycles later, you realize that you want to
  4408.                get rid off the old contents drawn upon the outer area and
  4409.                replace it by something new:
  4410.                ┌───────────────────────┐
  4411.                │ outer area (filled    │
  4412.                │ with background page) │
  4413.                │    ┌────────────┐ ▒▒▒ │
  4414.                │    │ animation  │ ▒3▒ │
  4415.                │    │ window    1│     │
  4416.                │    └────────────┘   2 │
  4417.                └───────────────────────┘
  4418.  
  4419.              To simplify that task, AniVGA checks the variable UpdateOuterArea
  4420.              each time Animate is called: if it is <>0, the area (2) becomes
  4421.              replaced by the respective contents of the background page and
  4422.              the variable is decremented by 1.
  4423.  
  4424. Note (!)   : - As AniVGA uses a page flipping scheme, you usually will set
  4425.                UpdateOuterArea:=2
  4426.                By that, AniVGA will update the screen area in the two next,
  4427.                successive calls to Animate, thus updating both visible pages
  4428.              - Of course, this routine will work with both possible background
  4429.                modes STATIC and SCROLLING
  4430.              - If you want to draw lines, pixels or text outside area 1, you
  4431.                must set WinClip:=FALSE to prevent AniVGA from automatically
  4432.                clipping!
  4433.              - Similiar, if you want to draw a sprite outside area 1, you
  4434.                must use SetSplitIndex() to tell AniVGA which sprites should
  4435.                not be clipped
  4436.              - You must use this variable whenever you painted something
  4437.                into the _background_ area and want to make it visible! This
  4438.                is especially true for BackgroundOutTextXY() and the like.
  4439.                Do not oversee that!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  4440.                (I bet people will do so, anyway and keep mailing me "hey,
  4441.                 I draw to the screen but don't see the changes"...)
  4442.              - Another nice trick is to use drawing routines to draw
  4443.                something at area 2 on both display pages 0 & 1: as AniVGA
  4444.                doesn't care for this area, it will stay there. Later on,
  4445.                when you want to get rid of the changes again, you set
  4446.                UpdateOuterArea:=2 and the next call of Animate() will wipe
  4447.                out area 2 with the contents of the original background image
  4448.                again
  4449.  
  4450. See also   : SetAnimateWindow, Animate
  4451.  
  4452.  
  4453. VIRTUAL COORDINATES - information
  4454. ─────────────────────────────────
  4455.  
  4456. See        : coordinates
  4457.  
  4458.  
  4459. WinClip, WinXMIN, WinXMAX, WinYMIN, WinYMAX - information
  4460. ─────────────────────────────────────────────────────────
  4461.  
  4462. Normally, the screen area (0,0)..(XMAX,YMAX) is identical to your animation
  4463. window (WinXMIN,WinYMIN)..(WinXMAX,WinYMAX), so clipping is unnecessary.
  4464. However, if you used SetAnimateWindow to define an animation window smaller
  4465. than your screen, (WinXMIN,WinYMIN)..(WinXMAX,WinYMAX) hold the boundaries
  4466. of this window.
  4467. This implies some special requirements: if you have a line, which lies
  4468. partially _outside_ the animation window, but still on the screen, should
  4469. this part be visible or not? Since there are good reasons for either case,
  4470. you decide how AniVGA shall treat this case: if you set WinClip:=TRUE, all
  4471. lines will be clipped to the animation window. WinClip:=FALSE (the default
  4472. value) prevents clipping so that you may draw to the outer area, too.
  4473.  
  4474. Note (!)   : - Only WinClip should be changed directly, all others are read-
  4475.                only and shouldn't be changed other than by SetAnimateWindow!
  4476.  
  4477. See also   : SetAnimateWindow
  4478.  
  4479.  
  4480. WriteBackgroundPage - procedure
  4481. ───────────────────────────────
  4482.  
  4483. Function   : Saves the background image to disk
  4484.  
  4485. Declaration: PROCEDURE WriteBackgroundPage(name:STRING); FAR;
  4486.  
  4487. Description: This is merely a shortcut of the WritePage()-procedure (see
  4488.              there), i.e. WritePage(name; BACKGNDPAGE) would do an equivalent
  4489.              job.
  4490.  
  4491. Note       : Possible ERROR-values returned are Err_FileIO
  4492.  
  4493. See also   : WritePage
  4494.  
  4495.  
  4496. WritePage - procedure
  4497. ─────────────────────
  4498.  
  4499. Function   : Saves a graphic page to disk
  4500.  
  4501. Declaration: PROCEDURE WritePage(name:STRING; pa:WORD); FAR;
  4502.  
  4503. Description: To save an image of one of the drawing pages (0 or 1), the
  4504.              backgroundpage BACKGNDPAGE (=2) or SCROLLPAGE (=3), specify the
  4505.              approriate page number in "pa" and a valid MSDOS-path/name where
  4506.              to store the data in "name".
  4507.  
  4508. Note       : - Make sure that your disk has enough space to hold the data: one
  4509.                page is stored as 64003 bytes!
  4510.              - You can't use this procedure for saving the background page
  4511.                "pa"=SCROLLPAGE in background mode SCROLLING!
  4512.              - Possible ERROR-values returned are: Err_InvalidPageNumber and
  4513.                Err_FileIO
  4514.  
  4515. See also   : WriteBackgroundPage, LoadPage
  4516.  
  4517.  
  4518. XMAX - constant
  4519. ───────────────
  4520.  
  4521. Function   : Specifies the maximal absolute x-coordinate
  4522.  
  4523. Declaration: CONST XMAX=319
  4524.  
  4525. Description: XMAX is the biggest _absolute_ coordinate in the x-direction
  4526.              which can be used: all x-coordinates must lie in the range
  4527.              0..XMAX.
  4528.  
  4529. Note       : Probably, you will never use this constant at all, because nearly
  4530.              everything in AniVGA's user interface works with _virtual_ coor-
  4531.              dinates, but who can tell...
  4532.  
  4533. See also   : YMAX, coordinates
  4534.  
  4535.  
  4536. XTiles - variable
  4537. ─────────────────
  4538.  
  4539. Function   : Holds the width of the scrollable background image in tiles
  4540.  
  4541. Declaration: VAR XTiles:INTEGER;
  4542.  
  4543. Description: When using background mode SCROLLING, you have to specify the
  4544.              size of your scrolling background area (with the
  4545.              SetBackgroundScrollRange()-procedure). AniVGA adjusts these
  4546.              values slightly and computes the size of the resulting background
  4547.              image in tiles.
  4548.          The width of this area (in tiles) is then stored in XTiles.
  4549.  
  4550. Note       : Don't change this variable directly!
  4551.  
  4552. See also   : YTiles, Background, SetBackgroundScrollRange
  4553.  
  4554.  
  4555. YMAX - constant
  4556. ───────────────
  4557.  
  4558. Function   : Specifies the maximal absolute y-coordinate
  4559.  
  4560. Declaration: CONST YMAX=199
  4561.  
  4562. Description: YMAX is the biggest _absolute_ y-coordinate which may be used,
  4563.              that is, every y-coordinate must lie in the range 0..YMAX.
  4564.  
  4565. Note       : Probably, you will never use this constant at all, because nearly
  4566.              everything in AniVGA's user interface works with _virtual_ coor-
  4567.              dinates, but who can tell...
  4568.  
  4569. See also   : XMAX, coordinates
  4570.  
  4571.  
  4572. YTiles - variable
  4573. ─────────────────
  4574.  
  4575. Function   : Holds the height of the scrollable background image in tiles
  4576.  
  4577. Declaration: VAR YTiles:INTEGER;
  4578.  
  4579. Description: When using background mode SCROLLING, you have to specify the
  4580.              size of your scrolling background area (with the
  4581.              SetBackgroundScrollRange()-procedure). AniVGA adjusts these
  4582.              values slightly and computes the size of the resulting background
  4583.              image in tiles.
  4584.              The height of this area (in tiles) is then stored in YTiles.
  4585.  
  4586. Note       : Don't change this variable directly!
  4587.  
  4588. See also   : XTiles, Background, SetBackgroundScrollRange
  4589.